Basado en mi experiencia, resumiré las diferencias clave en términos de rendimiento entre programas paralelos en CPU y GPU. Confíe en mí, una comparación puede cambiarse de generación en generación. Así que solo señalaré lo que es bueno y lo que es malo para CPU y GPU. Por supuesto, si realiza un programa en el extremo, es decir, teniendo lados malos o buenos, se ejecutará definitivamente más rápido en una plataforma. Pero una mezcla de esos requiere un razonamiento muy complicado.
nivel del programa host
Una diferencia clave es el costo de transferencia de memoria. Los dispositivos GPU requieren algunas transferencias de memoria. Este costo no es trivial en algunos casos, por ejemplo cuando tiene que transferir frecuentemente algunas matrices grandes. En mi experiencia, este costo se puede minimizar, pero empujando la mayor parte del código de host al código del dispositivo. Los únicos casos en los que puede hacerlo son cuando tiene que interactuar con el sistema operativo del host en el programa, como la salida al monitor.
nivel de programas de dispositivos
Ahora llegamos a ver un cuadro complejo que no ha sido plenamente revelado aún. Lo que quiero decir es que hay muchas escenas misteriosas en las GPU que no se han revelado. Pero aún así, tenemos mucha diferencia entre la CPU y la GPU (código del kernel) en términos de rendimiento.
Hay algunos factores que noté que contribuyen dramáticamente a la diferencia.
- de distribución de carga de trabajo
GPU, que consisten en muchas unidades de ejecución, están diseñados para manejar programas masivamente paralelos. Si tiene poco trabajo, digamos unas cuantas tareas secuenciales, y coloque estas tareas en una GPU, solo algunas de esas muchas unidades de ejecución están ocupadas, por lo tanto, serán más lentas que la CPU. Porque las CPU son, por otro lado, mejores para manejar tareas cortas y secuenciales. La razón es simple, las CPU son mucho más complicadas y pueden explotar el paralelismo del nivel de instrucción, mientras que las GPU explotan el paralelismo del nivel de subprocesos. Bueno, escuché que NVIDIA GF104 puede hacer Superscalar, pero no tuve la oportunidad de experimentarlo.
Vale la pena señalar que, en GPU, la carga de trabajo se divide en pequeños bloques (o grupos de trabajo en OpenCL) y los bloques se organizan en fragmentos, cada uno de los cuales se ejecuta en un procesador de transmisión (estoy usando terminologías de NVIDIA) . Pero en las CPU, esos bloques se ejecutan secuencialmente. No puedo pensar en nada más que en un solo bucle.
Por lo tanto, para los programas que tienen un número pequeño de bloques, será probable para ejecutar más rápido en las CPU.
- instrucciones de flujo de control
Las ramas son cosas malas a las GPU, siempre. Tenga en cuenta que las GPU prefieren cosas iguales. Bloques iguales, hilos iguales dentro de un bloque e hilos iguales dentro de un warp. Pero, ¿qué es lo que más importa?
***Branch divergences.***
Los programadores de Cuda/OpenCL odian las ramificaciones divergentes. Dado que todos los hilos de alguna manera se dividen en conjuntos de 32 hilos, llamados warp, y todos los hilos dentro de un warp se ejecutan en lockstep, una divergencia de rama causará que algunos hilos en el warp sean serializados. Por lo tanto, el tiempo de ejecución de la urdimbre se multiplicará en consecuencia.
A diferencia de las GPU, cada núcleo en las CPU puede seguir su propio camino. Además, las sucursales se pueden ejecutar de manera eficiente porque las CPU tienen predicción de bifurcación.
Por lo tanto, los programas que tienen más divergencias de distorsión son probablemente para que funcionen más rápido en las CPU.
- instrucciones de acceso a memoria
Esto realmente es bastante complicado por lo que vamos a hacer que breve.
Recuerde que los accesos a la memoria global tienen una latencia muy alta (400-800 ciclos). Entonces, en las generaciones anteriores de GPU, el hecho de si los accesos a la memoria se fusionaban era una cuestión crítica. Ahora su GTX560 (Fermi) tiene más 2 niveles de cachés. Por lo tanto, el costo de acceso a la memoria global se puede reducir en muchos casos. Sin embargo, las memorias caché en CPU y GPU son diferentes, por lo que sus efectos también son diferentes.
Lo que puedo decir es que realmente depende de su patrón de acceso a la memoria, su patrón de código kernel (cómo se intercalan los accesos de memoria con el cálculo, los tipos de operaciones, etc.) para saber si se ejecuta más rápido en GPU o CPUs
Pero de alguna manera puede esperar una gran cantidad de errores de caché (en las GPU) tiene un efecto muy malo en las GPU (¿qué tan mal? Depende de su código).
Además, la memoria compartida es una característica importante de las GPU. El acceso a la memoria compartida es tan rápido como acceder a la memoria caché GPU L1. Por lo tanto, los kernels que hacen uso de la memoria compartida tendrán mucho beneficio.
Algunos otros factores que realmente no he mencionado, pero los que pueden tener gran impacto en el rendimiento en muchos casos, como los conflictos de banco, el tamaño de la transacción de la memoria, la ocupación de la GPU ...
favor, lea [esta entrada del blog] (http://blog.stackoverflow.com/2011/08/gorilla-vs-shark/) antes de hacer más preguntas como esta en stackoverflow. – talonmies
@talonmies: No estoy de acuerdo: esta es una pregunta muy específica con una respuesta muy específica. El único punto en contra es que es * probablemente * un duplicado de alguna otra pregunta. –
posible duplicado de [GPGPU vs. Multicore?] (Http://stackoverflow.com/questions/5919172/gpgpu-vs-multicore) –