¿Cuándo debería descargar el trabajo a una GPU en lugar de a la CPU?

15

Se están creando sistemas más nuevos como OpenCL para que podamos ejecutar más y más código en nuestros procesadores gráficos, lo cual tiene sentido, porque deberíamos poder utilizar la mayor cantidad de potencia posible en nuestros sistemas.

Sin embargo, con todos estos nuevos sistemas, parece que las GPU son mejores que las CPU en todos los sentidos . Debido a que las GPU pueden hacer cálculos paralelos, las GPU multinúcleo en realidad parecen ser mucho mejores que las CPU multinúcleo; Podrías hacer muchos cálculos a la vez y realmente mejorar la velocidad. ¿Todavía hay ciertos casos en los que el procesamiento en serie es aún mejor, más rápido y / o más eficiente que el paralelo?

RétroX
fuente
66
No es realmente una pregunta sobre hardware. Debería volver a redactarse como "cuando es mejor programar la (s) CPU (es) que programar la (s) GPU (s)" y es una muy buena pregunta de IMO. Vea la etiqueta GPGPU entre otros en SO. Pero las preguntas de arquitectura "Qué tecnología usar" son mejores aquí que allá.
Kate Gregory
1
@Kate Ese ángulo parece estar muy bien cubierto en la pregunta de Superusuario vinculada. Al leerlo, estoy un poco sorprendido de que no haya migrado aquí, para ser honesto. Hay también esta en el SO. Volveré a abrir la pregunta (ya que tienes razón, los aspectos de programación son sobre el tema aquí). Espero que veamos una respuesta que no solo apunte a la cobertura existente (excelente) de este problema.
Adam Lear
1
Para el punto de @ Anna, creo que las respuestas deben ser mucho más acerca de cuándo un programador debe usar la GPU en lugar de una discusión puramente teórica sobre cuál es la diferencia entre una GPU y una CPU. He editado el título para reflejar esto.
2
@RetroX No podemos cerrar las preguntas como duplicados si están en sitios diferentes.
Adam Lear

Respuestas:

26

Sin embargo, con todos estos nuevos sistemas, parece que las GPU son mejores que las CPU en todos los sentidos.

Este es un malentendido fundamental. Los núcleos de GPU actuales siguen siendo limitados en comparación con las CPU de línea superior actuales. Creo que la arquitectura Fermi de NVIDIA es la GPU más potente actualmente disponible. Tiene solo registros de 32 bits para la aritmética de enteros, y menos capacidad para la predicción de ramificaciones y la ejecución especulativa que un procesador Intel actual. Los chips Intel i7 proporcionan tres niveles de almacenamiento en caché, los núcleos de Fermi solo tienen dos, y cada caché en el Fermi es más pequeño que el caché correspondiente en el i7. La comunicación entre procesos entre los núcleos de la GPU es bastante limitada, y sus cálculos deben estructurarse para adaptarse a esa limitación (los núcleos se agrupan en bloques, y la comunicación entre núcleos en un bloque es relativamente rápida, pero la comunicación entre bloques es lenta).

Una limitación significativa de las GPU actuales es que todos los núcleos deben ejecutar el mismo código. A diferencia de los núcleos en su CPU, no puede decirle a un núcleo de GPU que ejecute su cliente de correo electrónico y a otro núcleo para ejecutar su servidor web. Usted le da a la GPU la función de invertir una matriz, y todos los núcleos ejecutan esa función en diferentes bits de datos.

Los procesadores en la GPU viven en un mundo aislado. Pueden controlar la pantalla, pero no tienen acceso al disco, la red o el teclado.

El acceso al sistema GPU tiene costos generales considerables. La GPU tiene su propia memoria, por lo que sus cálculos se limitarán a la cantidad de memoria en la tarjeta GPU. La transferencia de datos entre la memoria de la GPU y la memoria principal es relativamente costosa. Pragmáticamente, esto significa que no hay ningún beneficio en entregar un puñado de cálculos cortos de la CPU a la GPU, porque los costos de instalación y desmontaje reducirán el tiempo requerido para hacer el cálculo.

La conclusión es que las GPU son útiles cuando tienes muchas (como en cientos o miles) de copias de un cálculo largo que se pueden calcular en paralelo. Las tareas típicas para las que esto es común son la informática científica, la codificación de video y la representación de imágenes. Para una aplicación como un editor de texto, la única función en la que una GPU podría ser útil es representar el tipo en la pantalla.

Charles E. Grant
fuente
El soporte de doble precisión es parte del Shader Model 5, y AMD / ATI también lo tiene.
Ben Voigt
@Ben, gracias por la corrección. He eliminado la declaración incorrecta.
Charles E. Grant
11

Las GPU no son procesadores generalistas como lo son las CPU. Se especializan en hacer una cosa muy específica: aplicar el mismo código a una gran cantidad de datos, y lo hacen muy, muy bien, mucho mejor que una CPU. Pero la mayoría de las aplicaciones no se trata de aplicar el mismo código a una gran cantidad de datos; se trata de un bucle de eventos: esperar entrada, leer la entrada, actuar sobre ella y luego esperar más entrada. Ese es un proceso bastante serial, y las GPU apestan en "serial".

Cuando tiene una gran cantidad de datos que necesita procesar, y cada elemento puede procesarse en paralelo, independientemente de los demás, continúe y envíelo a la GPU. Pero no piense en esto como "el nuevo paradigma" en el que todo tiene que exprimirse.

Esta pregunta está etiquetada como "optimización", así que recuerde tratarla como una. Aplique la optimización de GPU donde las pruebas y los perfiles revelan que se necesita optimización y la naturaleza de la tarea es tal que se puede aplicar la optimización de GPU. De lo contrario, no te molestes, ya que eso sería una optimización prematura o incorrecta, lo que causa más problemas de los que soluciona.

Mason Wheeler
fuente
8

La respuesta simple es que una GPU funciona mejor cuando necesita hacer un cálculo bastante pequeño y bastante simple en cada uno de una gran cantidad de elementos. Para lograr mucho de esta manera, el cálculo de cada elemento debe ser independiente de los cálculos de los otros elementos. Si hay (normalmente) alguna dependencia entre un elemento y otro, generalmente necesita encontrar alguna forma de romperlo antes de sacar mucho provecho de la ejecución de ese código en la GPU. Si la dependencia no puede romperse en absoluto, o requiere demasiado trabajo para romper, el código podría ejecutarse más rápido en la CPU.

La mayoría de las CPU actuales también admiten bastantes tipos de operaciones que las GPU actuales simplemente no intentan admitir en absoluto (por ejemplo, protección de memoria para multitarea).

Mirándolo desde una dirección ligeramente diferente, las CPU han sido (en gran parte) diseñadas para ser razonablemente convenientes para los programadores, y la gente del hardware ha hecho todo lo posible (¡y lo mejor es lo mejor!) Para crear hardware que mantenga ese modelo conveniente para el programador, pero aún se ejecuta lo más rápido posible.

Las GPU vienen en una dirección bastante opuesta: están diseñadas en gran medida para ser convenientes para el diseñador de hardware, y cosas como OpenCL han intentado proporcionar un modelo de programación tan razonable como sea posible dadas las limitaciones del hardware.

Escribir código para ejecutarse en una GPU generalmente requerirá más tiempo y esfuerzo (por lo que costará más) que hacer lo mismo en la CPU. Como tal, hacerlo tiene sentido principalmente cuando / si:

  1. El problema es tan paralelo que puede esperar una gran ganancia con un esfuerzo mínimo, o
  2. La ganancia de velocidad es tan importante que justifica mucho trabajo extra.

Hay algunas posibilidades obvias para cada uno, pero una gran cantidad de aplicaciones claramente ni siquiera están cerca de ninguna de ellas. Me sorprendería bastante ver (por ejemplo) una aplicación CRUD que se ejecuta en una GPU en el corto plazo (y si lo hace, probablemente sucederá porque alguien se propuso con ese objetivo exacto en mente, no necesariamente algo que se aproxime a un óptimo relación costo / beneficio).

La realidad es que para muchas aplicaciones (estoy tentado a decir "la mayoría"), una CPU típica es mucho más que lo suficientemente rápida, y la conveniencia de la programación (que lleva a cosas como el desarrollo más fácil de nuevas características) es mucho más importante que velocidad de ejecución

Jerry Coffin
fuente
3

Podrías hacer muchos cálculos a la vez y realmente mejorar la velocidad.

mejorar la velocidad? ¿Y qué? Hasta el año pasado solo recuerdo una o dos veces cuando era necesario. La mayoría de las veces me han pedido que modifique o arregle la lógica, que se ajuste a una fuente de datos diferente, que mejore la interacción del usuario, etc. La única velocidad que los clientes estaban interesados ​​en estos casos era la velocidad de hacer un cambio. "Suelte la nueva función en un mes, o mejor aún, en dos semanas".

No me malinterpreten: como codificador disfruto apretando los tics de la CPU a fondo. Es solo que este arte no suele tener una gran demanda.

¿Todavía hay ciertos casos en los que el procesamiento en serie es aún mejor, más rápido y / o más eficiente que el paralelo?

Yo diría que hay muchos casos. El procesamiento en serie es más simple que el paralelo, lo que lo hace más eficiente en todos los casos en que la velocidad no es un requisito crítico. El procesamiento en serie permite una implementación más fácil de la lógica complicada y la interfaz de usuario, es más fácil especificar y probar, mantener y cambiar.

Como regla, el procesamiento en serie permite una expresión más clara de la intención del programador y una lectura más fácil del código. Diría que ahorra los recursos más preciados y escasos: el cerebro del programador.

mosquito
fuente
2

Las CPU son aún más versátiles. Por ejemplo, las GPU son más eficientes que las CPU en precisión simple, pero no en precisión doble. Hay muchas más bibliotecas para CPU que para GPU.

cuant_dev
fuente
3
¿Puedes entrar en un poco más de detalle? Usted ha proporcionado tres declaraciones sin información o explicación sobre la veracidad de ellas.
Bueno, la falta de cálculos eficientes de doble precisión es de conocimiento común: en.wikipedia.org/wiki/GPGPU
quant_dev
@quant: su información está al menos 2 años desactualizada: 544 GigaFLOPS es mucho más rápido que cualquier CPU convencional.
Ben Voigt
@Ben No veo dónde su enlace menciona el rendimiento de doble precisión.
quant_dev
@quant: awurl.com/Tt7LAX8lH
Ben Voigt
2

La regla simple es, si lo que está haciendo puede expresarse en términos de construcciones de álgebra lineal y es crítico en el tiempo, hágalo en la GPU; de lo contrario, use la CPU.

Las GPU no son como un gran número de CPU, tienen características de rendimiento muy diferentes.

dan_waterworth
fuente
Si es "tiempo crítico", probablemente no tenga tiempo para reconfigurar la GPU para un sombreador de cómputo y cargar los datos. Son los grandes problemas los que más se benefician.
Ben Voigt
@Ben, creo que tenemos diferentes definiciones de "tiempo crítico", lo que quiero decir es que el cálculo está en la ruta crítica durante una cantidad de tiempo significativa.
dan_waterworth
1

Si necesita un crujido de números sin procesar, las GPU son el camino a seguir. Sin embargo, todas esas ALU significan que hay menos transistores dedicados a los circuitos de control de flujo (ramificación). Entonces, si necesita escribir algo que necesita mucho flujo de control complejo, muchos condicionales, etc., una CPU será más rápida.

Alex
fuente