vectores una programacion multiplicacion matriz matrices matematicas extraer elementos columna agregar optimization gcc matrix linear-algebra compiler-flags

optimization - una - multiplicacion de matrices



Indicadores de optimización de GCC para operaciones de matriz/vector (1)

Estoy realizando operaciones matriciales usando C. Me gustaría saber cuáles son los diversos indicadores de optimización del compilador para mejorar la velocidad de ejecución de estas operaciones matriciales para datos dobles e int64, como Multiplicación, Inversa, etc. No estoy buscando código optimizado a mano , Solo quiero hacer que el código nativo sea más rápido usando los indicadores del compilador y obtener más información sobre estos indicadores.

Las banderas que he encontrado hasta ahora mejoran el código de la matriz.

-O3/O4 -funroll-loops -ffast-math


Antes que nada, no recomiendo usar -ffast-math por las siguientes razones:

  1. Se ha demostrado que el rendimiento se degrada cuando se utiliza esta opción en la mayoría (si no en todos) los casos. Entonces, "matemáticas rápidas" no es tan rápido.

  2. Esta opción rompe el estricto cumplimiento IEEE en operaciones de punto flotante que finalmente resulta en la acumulación de errores computacionales de naturaleza impredecible.

  3. Es posible que obtengas resultados diferentes en diferentes entornos y la diferencia puede ser considerable. El término entorno (en este caso) implica la combinación de: hardware, sistema operativo, compilador. Lo que significa que la diversidad de situaciones en las que puede obtener resultados inesperados tiene un crecimiento exponencial.

  4. Otra triste consecuencia es que los programas que enlazan con la biblioteca creada con esta opción pueden esperar una matemática de coma flotante correcta (IEEE), y aquí es donde se rompen sus expectativas, pero será muy difícil averiguar por qué.

  5. Por último, eche un vistazo a este artículo .

Por las mismas razones, debe evitar -Ofast (ya que incluye el mal -ffast-math ). Extraer:

-Ofast

Ignore el cumplimiento estricto de las normas. -Ofast habilita todas las optimizaciones de -Ofast . También permite optimizaciones que no son válidas para todos los programas que cumplen con los estándares. Enciende -ffast-math y Fortran -fno-protect-parens y -fstack-arrays .

No existe una bandera como -O4 . Al menos no estoy al tanto de eso, y no hay rastros en la documentación oficial de GCC. Por lo tanto, el máximo en este sentido es -O3 y definitivamente debería usarlo, no solo para optimizar las matemáticas, sino también para las compilaciones de versiones en general.

-funroll-loops es una muy buena opción para rutinas matemáticas, especialmente involucrando operaciones de vector / matriz donde el tamaño del bucle se puede deducir en tiempo de compilación (y como resultado desenrollado por el compilador).

Puedo recomendar 2 banderas más: -march=native y -mfpmath=sse . De forma similar a -O3 , -march=native es bueno, en general, para compilaciones de versiones de cualquier software y no solo intensivas en matemática. -mfpmath=sse habilita el uso de registros XMM en instrucciones de punto flotante (en lugar de apilar en modo x87 ).

Además, me gustaría decir que es una lástima que no desee modificar su código para obtener un mejor rendimiento ya que esta es la principal fuente de aceleración para las rutinas de vectores / matrices. Gracias a SIMD , SSE Intrinsics y Vectorización , el código de álgebra lineal pesada puede ser de mayor magnitud que sin ellos. Sin embargo, la aplicación adecuada de estas técnicas requiere un conocimiento profundo de sus aspectos internos y bastante tiempo / esfuerzo para modificar (en realidad reescribir) el código.

Sin embargo, hay una opción que podría ser adecuada en su caso. GCC ofrece auto-vectorización que se puede habilitar por -ftree-vectorize , pero no es necesario ya que está utilizando -O3 (porque ya incluye -ftree-vectorize ). El punto es que aún debes ayudar un poco a GCC a entender qué código puede auto-vectorizarse. Las modificaciones suelen ser menores (si es necesario), pero debe familiarizarse con ellas. Vea la sección de Bucles Vectorizable en el enlace de arriba.

Finalmente, le recomiendo que busque en Eigen , la biblioteca basada en plantillas de C ++ que tiene una implementación altamente eficiente de las rutinas de álgebra lineal más comunes. Utiliza todas las técnicas mencionadas aquí hasta ahora de una manera muy inteligente. La interfaz es puramente orientada a objetos, ordenada y agradable de usar. El enfoque orientado a objetos parece muy relevante para el álgebra lineal, ya que generalmente manipula los objetos puros como matrices, vectores, cuaterniones, rotaciones, filtros, etc. Como resultado, al programar con Eigen, nunca tendrá que ocuparse de conceptos de bajo nivel (como SSE, Vectorización, etc.) usted mismo, sino simplemente disfrutar la resolución de su problema específico.