Se gfortran o ifort compiladores sabiamente el uso de instrucciones SIMD cuando se suma el producto de dos matrices?
-
22-12-2019 - |
Pregunta
Tengo un código, escrito con numpy, y estoy considerando la posibilidad de portarlo a Fortran para un mejor rendimiento.
Una operación hago varias veces es sumar el elemento sabio producto de dos matrices:
sum(A*B)
Parece fundida multiplicar-agregar las instrucciones para ayudar con esto.Mi actual procesador no es compatible con estas instrucciones, así que no puedo probar cosas todavía.Sin embargo, puedo actualizar a un nuevo procesador que no admite FMA3 (un Intel Haswell procesador).
¿Alguien sabe si compilar el programa con "-march=native" (o el ifort equivalente) será suficiente para que el compilador (ya sea gfortran o ifort) el uso inteligente instrucciones SIMD para optimizar ese código, ¿o crees que voy a tener al bebé, los compiladores o el código?
Solución 3
Gracias a Xiaolei de Zhu punta, ahora sé que gfortran utilizará fusionado multiplicar-agregar a optimizar sum(A*B)
.Por ejemplo, con este código:
programa de prueba implícito ninguno
real, dimension(7) ::a, b
un = (/ 2.0, 3.0, 5.0, 7.0, 11.0, 13.0, 17.0 /)
b = (/ 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0 /)
print *, suma(a*b)
endprogram
Puedo compilar con f95 sum.f95 -o sum -O3 -march=core-avx2
, y objdump -d sum | grep vfmadd
muestra
40088b:c4 e2 71 99 44 24 30 vfmadd132ss 0x30(%der),%xmm1,%xmm0
400892:c4 e2 69 b9 44 24 34 vfmadd231ss 0x34(%der),%xmm2,%xmm0
400899:c4 e2 61 b9 44 24 38 vfmadd231ss 0x38(%der),%xmm3,%xmm0
4008a0:c4 e2 59 b9 44 24 3c vfmadd231ss 0x3c(%der),%xmm4,%xmm0
4008a7:c4 e2 51 b9 44 24 40 vfmadd231ss 0x40(%der),%xmm5,%xmm0
4008ae:c4 e2 49 b9 44 24 44 vfmadd231ss 0x44(%der),%xmm6,%xmm0
4008b5:c4 e2 41 b9 44 24 48 vfmadd231ss 0x48(%der),%xmm7,%xmm0
Así gfortran desenrolla el lazo y poner en 7 fusionado multiplicar-agregar instrucciones.Si puedo crear más grande, al azar, matrices multidimensionales, todavía veo vfmadd231ss pop-up una vez (para que no desenrollar el bucle).
Otros consejos
Si usted utiliza -march=native
en una máquina con SIMD, el compilador debe generar instrucciones SIMD, aunque yo siempre he utilizado -xHost
indicador de lugar con ifort.
Pero yo no estoy tan seguro de cómo hacer que ellos lo hagan "con prudencia".Mi sensación es que en -O3
nivel ifort y gfortran ambos tienden a ser demasiado agresivo en la vectorización (es decir, usan la SIMD funcionalidad, más a menudo de lo que debería).Muy a menudo tengo que apagar la vectorización para obtener el código más eficiente.Esto, por supuesto, puede o no puede ser verdad para usted.
Normalmente es mejor utilizar el vector de las bibliotecas que están optimizados para esta tarea.Puede utilizar vdmul
en MKL o gsl_vector_mul
en GSL para ello.
El uso de -march=NEWARCH
el resultado será un código de sintonía para la arquitectura NEWARCH pero no se puede ejecutar en una versión anterior de la arquitectura.Usted puede utilizar el -mtune=NEWARCH
bandera donde NEWARCH es la arquitectura de su nuevo procesador.Esto va a generar código atentos a la nueva arquitectura, pero aún ejecutable en el antiguo.Dado que aún no tienes la nueva máquina, -mtune
es probablemente lo que usted necesita en el momento.
Con ifort puede utilizar vectorización informe banderas para mostrar que parte del programa ha sido vectorizados.Por ejemplo, ifort
bandera -vec-report=1
le dará esa información durante la compilación.Estoy seguro que no va a ser un equivalente de la bandera en gfortran.
gfortran versiones, donde sum(a*b)
dio una mejor vectorización de dot_product(a,b)
son de larga obsoletos.El código que muestran es el uso de serie AVX2 fma instrucciones.
En la aplicación de dot_product
sin indirecto de indexación o de otras complicaciones (un simple bucle por sí mismo), fma probablemente será más lento que la combinación de simd multiplicaciones y añadir instrucciones, porque al multiplicar se puede hacer fuera de la latencia de la ruta crítica.gfortran uso de paralelo simd fma para dot_product puede ser muy eficaz en los casos más complicados.
Usted necesitará -O2 -ftree-vectorize -ffast-math -march=native or -O3 -ffast-math -march=native
(así como vector de longitud) para vectorizar esta, y gfortran puede fallar para vectorizar dentro de una región paralela de OpenMP.
gfortran 4.9 parece haber descartado la opción -ftree-vectorizador-verbose.-fdump-árbol-vect escribe los detalles de la vectorización se la pasa a un .vect archivo, con diferentes nombres elegidos para los diferentes gcc versiones.