Pregunta

¿Alguien ha aprovechado la vectorización automática que puede hacer gcc? ¿En el mundo real (en oposición al código de ejemplo)? ¿Se necesita una reestructuración del código existente para aprovechar? ¿Hay un número significativo de casos en algún código de producción que pueda vectorizarse de esta manera?

¿Fue útil?

Solución

Todavía no he visto que GCC o Intel C ++ vectoricen automáticamente cualquier cosa excepto bucles muy simples, incluso cuando se me da el código de algoritmos que pueden (y fueron, después de que los reescribí manualmente utilizando SSE intrínsicos) se vectorizaran.

Parte de esto es ser conservador, especialmente cuando se enfrenta a un posible alias de puntero, puede ser muy difícil para un compilador de C / C ++ "probarse" a sí mismo que una vectorización sería segura, incluso si usted como programador sabe que está. La mayoría de los compiladores (sensiblemente) prefieren no optimizar el código en lugar de arriesgarse a compilarlo. Esta es un área en la que los lenguajes de nivel superior tienen una ventaja real sobre C, al menos en teoría (lo digo en teoría, ya que no tengo conocimiento de ningún compilador de ML o Haskell que vectorice automáticamente).

Otra parte es simplemente las limitaciones analíticas: la mayoría de las investigaciones en vectorización, según entiendo, están relacionadas con la optimización de los problemas numéricos clásicos (dinámica de fluidos, por ejemplo), que era el pan y la mantequilla de la mayoría de las máquinas de vectores antes de hace unos años (cuando , entre CUDA / OpenCL, Altivec / SSE y la célula STI, la programación de vectores en varias formas llegó a estar ampliamente disponible en los sistemas comerciales).

Es bastante improbable que el código escrito para un procesador escalar en mente sea fácil de vectorizar para un compilador. Afortunadamente, hay muchas cosas que puede hacer para que un compilador pueda entender cómo vectorizarlo, como el mosaico de bucles y el desenrollado parcial, y también (tiende a) ayudar al rendimiento en los procesadores modernos, incluso si el compilador no encuentra la manera de hacerlo. vectorizarlo.

Otros consejos

Es difícil de usar en cualquier lógica empresarial, pero aumenta la velocidad cuando se procesan volúmenes de datos de la misma manera.

Un buen ejemplo es el procesamiento de sonido / video donde se aplica la misma operación a cada muestra / píxel. He utilizado VisualDSP para esto, y tuvo que comprobar los resultados después de compilar, si realmente se usa donde debería.

La vectorización será principalmente útil para programas numéricos. Los programas vectorizados pueden ejecutarse más rápido en procesadores vectoriales, como el procesador celular STI que se usa en las consolas de juegos PS3. Allí, los cálculos numéricos utilizados en, por ejemplo, la representación de los gráficos del juego se pueden acelerar mucho mediante la vectorización. Dichos procesadores se denominan procesadores SIMD (datos de instrucción múltiple única).

En otros procesadores no se utilizará la vectorización. Los programas vectorizados se ejecutan en un conjunto de instrucciones vectorizadas que no serán aplicables a un procesador que no sea SIMD.

La serie de procesadores Nehalem de Intel (lanzada a fines de 2008) implementa instrucciones SSE 4.2, que son instrucciones SIMD. Fuente: wikipedia .

Las instrucciones vectorizadas no se limitan a los procesadores celulares: la mayoría de las estaciones de trabajo modernas, como las de la CPU, las tienen (PPC, x86 desde Pentium 3, Sparc, etc.). Cuando se usa bien para operaciones de puntos flotantes, puede ayudar bastante para tareas muy informáticas (filtros, etc.). En mi experiencia, la vectorización automática no funciona tan bien.

Es posible que haya notado que casi nadie sabe realmente cómo hacer un buen uso de la Vectorización Automática de GCC. Si busca en la web para ver los comentarios de las personas, siempre se le ocurre la idea de que GCC le permite habilitar la vectorización automática, pero en muy raras ocasiones hace un uso real de la misma, por lo que si desea utilizar la aceleración SIMD (por ejemplo: MMX, SSE, AVX, NEON, AltiVec), entonces básicamente tiene que averiguar cómo escribirlo usando los compiladores intrínsecos o el código de lenguaje ensamblador.

Pero el problema con los intrínsecos es que efectivamente necesita entender el lado del lenguaje ensamblador y luego aprender el método intrínseco de describir lo que quiere, lo que probablemente resulte en un código mucho menos eficiente que si lo escribiera Código de ensamblaje (como por un factor de 10x), porque el compilador todavía tendrá problemas para hacer un buen uso de sus instrucciones intrínsecas.

Por ejemplo, podría estar usando SIMD Intrinsics para que se puedan realizar muchas operaciones en paralelo al mismo tiempo, pero su compilador probablemente generará un código de ensamblaje que transfiere los datos entre los registros SIMD y los registros normales de la CPU y viceversa. ¡hacer que su código SIMD se ejecute efectivamente a una velocidad similar (o incluso más lenta) que el código normal!

Básicamente:

  • Si quieres hasta un 100% de aceleración (2x velocidad), entonces o bien comprar el Compiladores oficiales de Intel / ARM o convierta parte de su código para usar SIMD C / C ++ Intrinsics.
  • si usted quiere un 1000% de aceleración (velocidad 10x), entonces Escríbelo a mano en el código de ensamblaje usando las instrucciones SIMD. O si está disponible en su hardware, use la aceleración de la GPU como OpenCL o el CUDA SDK de Nvidia, ya que pueden proporcionar aceleraciones similares en la GPU como SIMD en la CPU.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top