¿Hay algún beneficio por usar la CPU en lugar de la GPU?

63

He estado investigando procesadores y tarjetas gráficas, y descubrí que las GPU son mucho más rápidas que las CPU. Leí en este artículo , una GPU Nvidia de 2 años superó 14 veces el procesador Intel Core I7 de 3.2GHz en ciertas circunstancias. Si las GPU son tan rápidas, ¿por qué los desarrolladores no las usan para todas las funciones de un juego? ¿Es posible que las GPU hagan algo más que gráficos?

Daniel Pendergast
fuente
17
Si estás en un juego en el que estás descargando todo a la GPU y tu CPU apenas está haciendo nada, entonces puedes obtener un aumento en el rendimiento al volver a cargar parte de la carga en la CPU.
Tetrad
3
su GPU es quizás mejor que su CPU, pero no creo que su tarjeta de video sea mejor que su placa base (y no compararé el sistema operativo con el controlador jajaja)
e-MEE
27
GPU is faster than a CPUEs un falso mito que muchas personas se hacen creer después de ver puntos de referencia basados ​​en problemas específicamente diseñados para GPU (esta clase de problemas se llaman "problemas vergonzosamente paralelos"), vea mi respuesta en esta pregunta de Superusuario: ¿Por qué seguimos usando ¿CPU en lugar de GPU?
Lie Ryan
55
Un beneficio es que cada computadora tiene una CPU :)
Tim Holt

Respuestas:

50

"He leído que los autos F1 son más rápidos que los que manejamos en las calles ... ¿por qué la gente no usa autos F1 entonces?" Bueno ... La respuesta a esta pregunta es simple: los autos F1 no pueden romperse o girar tan rápido como la mayoría de los autos (el auto más lento podría vencer a un F1 en ese caso). El caso de las GPU es muy similar, son buenas para seguir una línea recta de procesamiento, pero no son tan buenas cuando se trata de elegir diferentes rutas de procesamiento.

Un programa ejecutado en la GPU tiene sentido cuando debe ejecutarse muchas veces en paralelo, por ejemplo, cuando tiene que mezclar todos los píxeles de la Textura A con píxeles de la Textura B y ponerlos todos en la Textura C. Esta tarea, cuando se ejecuta en una CPU, se procesaría de la siguiente manera:

for( int i =0; i< nPixelCount; i++ )
     TexC[i] = TexA[i] + TexB[i];

Pero esto es lento cuando tiene que procesar muchos píxeles, por lo que la GPU en lugar de usar el código anterior, solo usa el siguiente:

     TexC[i] = TexA[i] + TexB[i];

y luego completa todos los núcleos con este programa (esencialmente copiando el programa al núcleo), asignando un valor ipara cada uno. Entonces es de donde viene la magia de la GPU y hacer que todos los núcleos ejecuten el programa al mismo tiempo , haciendo muchas operaciones mucho más rápido de lo que podría hacer el programa lineal de la CPU.

Esta forma de trabajar está bien cuando tiene que procesar de la misma manera una gran cantidad de entradas pequeñas, pero es realmente malo cuando tiene que hacer un programa que pueda tener ramificación condicional. Así que ahora veamos qué hace la CPU cuando se trata de alguna verificación de condición:

  • 1: ejecutar el programa hasta la primera operación lógica
  • 2: evaluar
  • 3: Continúe ejecutando desde el resultado de la dirección de memoria de la comparación (como con una instrucción JNZ asm)

Esto es muy rápido para que la CPU establezca un índice, pero para que la GPU haga lo mismo, es mucho más complicado. Debido a que la potencia de la GPU proviene de ejecutar la misma instrucción al mismo tiempo (son núcleos SIMD), deben estar sincronizados para poder aprovechar la arquitectura del chip. Tener que preparar la GPU para tratar con sucursales implica más o menos:

  • 1: Haga una versión del programa que siga solo a la rama A, complete este código en todos los núcleos.
  • 2: ejecutar el programa hasta la primera operación lógica
  • 3: evaluar todos los elementos
  • 4: Continúe procesando todos los elementos que siguen a la rama A, ponga en cola todos los procesos que eligieron la ruta B (¡para lo cual no hay ningún programa en el núcleo!). ¡Ahora todos los núcleos que eligieron la ruta B estarán inactivos! El peor de los casos es la ejecución de un solo núcleo y todos los demás núcleos solo esperan.
  • 5: Una vez que todos los As hayan terminado de procesarse, active la versión de la rama B del programa (copiándola de los búferes de memoria a alguna pequeña memoria central).
  • 6: Ejecute la rama B.
  • 7: Si es necesario, combine / combine ambos resultados.

Este método puede variar en función de muchas cosas (es decir, algunas muy pequeñaslas sucursales pueden ejecutarse sin la necesidad de esta distinción), pero ahora ya puede ver por qué la ramificación sería un problema. Los cachés de GPU son muy pequeños, no puede simplemente ejecutar un programa desde la VRAM de forma lineal, tiene que copiar pequeños bloques de instrucciones en los núcleos para ejecutarlos y si tiene ramas suficientes, su GPU se detendrá en su mayoría en lugar de ejecutar cualquier código, que no tiene sentido cuando se trata de ejecutar un programa que solo sigue una rama, como la mayoría de los programas, incluso si se ejecuta en múltiples hilos. En comparación con el ejemplo de F1, esto sería como tener que abrir paracaídas de frenado en cada esquina, luego salir del automóvil para empacarlos nuevamente dentro del automóvil hasta la siguiente esquina que desea girar nuevamente o encontrar un semáforo rojo (la siguiente esquina más probable).

Luego, por supuesto, está el problema de que otras arquitecturas sean tan buenas en la tarea de operaciones lógicas, mucho más baratas y más confiables, estandarizadas, más conocidas, eficientes en energía, etc. Las tarjetas de video más nuevas son apenas compatibles con las antiguas sin emulación de software. use diferentes instrucciones asm entre ellas, incluso del mismo fabricante, y que por el momento la mayoría de las aplicaciones de computadora no requieren este tipo de arquitectura paralela, e incluso si las necesitan, pueden usarlas a través de API estándar como OpenCL como mencionado por eBusiness, o a través de las API de gráficos. Probablemente en algunas décadas tendremos GPU que puedan reemplazar las CPU, pero no creo que suceda pronto.

Recomiendo la documentación de la aplicación AMD que explica mucho sobre su arquitectura de GPU y también vi sobre los NVIDIA en los manuales de CUDA, que me ayudaron mucho a entender esto. Todavía no entiendo algunas cosas y puedo estar equivocado, probablemente alguien que sepa más pueda confirmar o negar mis declaraciones, lo que sería genial para todos nosotros.

Pablo Ariel
fuente
66
analogía extraña pero es un buen punto que the fastest isn't always the fastest.
Lie Ryan
1
¡Gracias! Creo que es un tema interesante porque vincula muchos conceptos de programación de juegos a la forma en que funciona el hardware, algo olvidado en la tierra de los lenguajes de alto nivel actuales. Hay algunas otras cosas que me gustaría agregar, pero escribir la respuesta ya tomó algún tiempo, así que intentaré actualizarlo más tarde, como las capacidades de "modo protegido" de las CPU, la velocidad del bus de memoria, etc. pero espero que esto aclare Algunos inconvenientes técnicos de ejecutar todo en la GPU.
Pablo Ariel
66
La analogía sería mucho mejor si fuera precisa. Los autos de F1 tienen una tremenda capacidad de frenado que les permite mantener la alta velocidad en una curva en lugar de comenzar a frenar con mucha anticipación. Las curvas a alta velocidad también son mejores gracias a las altas fuerzas aerodinámicas, aunque el radio de giro probablemente no sea excelente para los estacionamientos. Las mejores razones podrían incluir la falta de espacio de almacenamiento, espejo retrovisor, aire acondicionado, control de crucero, protección contra los elementos, asientos de pasajeros, suspensión y distancia al suelo para manejar carreteras en mal estado, o varias otras cosas comunes en los vehículos de pasajeros.
GargantuChet
55
@Pablo Ariel Estoy respondiendo a la declaración: "Los autos F1 no pueden romperse ni girar tan rápido como la mayoría de los autos". Usted sugiere que los autos F1 solo pueden acelerar en línea recta y no son muy buenos en las curvas o durante la desaceleración. Pero los autos de F1 en realidad pueden frenar mucho más rápido que "la mayoría de los autos", y son excelentes en las curvas de alta velocidad.
GargantuChet
44
La analogía es más precisa si piensas en Dragsters que en autos de F1
Agustin Meriles
32

Las GPU son muy buenas para tareas paralelas. Lo cual es genial ... si estás ejecutando tareas paralelas.

Los juegos son sobre el tipo de aplicación menos paralelizable. Piensa en el ciclo principal del juego. La IA (supongamos que el jugador se maneja como un caso especial de la IA) debe responder a las colisiones detectadas por la física. Por lo tanto, debe ejecutarse después. O al menos, la física necesita llamar a las rutinas de IA dentro de los límites del sistema de física (que generalmente no es una buena idea por muchas razones). Los gráficos no pueden ejecutarse hasta que la física se haya ejecutado, porque la física es lo que actualiza la posición de los objetos. Por supuesto, la IA también debe ejecutarse antes de renderizar, ya que la IA puede generar nuevos objetos. Los sonidos deben ejecutarse después de la IA y los controles del jugador

En general, los juegos pueden enhebrarse de muy pocas maneras. Los gráficos se pueden dividir en un hilo; el bucle del juego puede meter un montón de datos en el hilo de gráficos y decir: renderizar esto. Puede hacer una interpolación básica, de modo que el bucle principal del juego no tenga que estar sincronizado con los gráficos. El sonido es otro hilo; el bucle del juego dice "juega esto", y se juega.

Después de eso, todo comienza a ser doloroso. Si tiene algoritmos de ruta complejos (como los de RTS), puede enhebrarlos. Los algoritmos pueden tardar algunos marcos en completarse, pero al menos serán concurrentes. Más allá de eso, es bastante difícil.

Entonces estás viendo 4 hilos: juego, gráficos, sonido y posiblemente procesamiento de IA a largo plazo. Eso no es mucho. Y eso no es suficiente para las GPU, que pueden tener literalmente cientos de hilos en vuelo a la vez. Eso es lo que les da a las GPU su rendimiento: poder utilizar todos esos hilos a la vez. Y los juegos simplemente no pueden hacer eso.

Ahora, tal vez pueda ser "amplio" para algunas operaciones. Las IA, por ejemplo, suelen ser independientes entre sí. Por lo tanto, puede procesar varias docenas de IA a la vez. Justo hasta que realmente necesites hacerlos dependientes el uno del otro. Entonces estás en problemas. Los objetos de física son igualmente independientes ... a menos que haya una restricción entre ellos y / o choquen con algo. Entonces se vuelven muy dependientes.

Además, existe el hecho de que la GPU simplemente no tiene acceso a la entrada del usuario, que, según tengo entendido, es algo importante para los juegos. Entonces eso tendría que ser proporcionado. Tampoco tiene acceso directo a archivos ni ningún método real de hablar con el sistema operativo; así que de nuevo, tendría que haber algún tipo de forma de proporcionar esto. Ah, y todo ese procesamiento de sonido? Las GPU no emiten sonidos. Entonces esos tienen que volver a la CPU y luego al chip de sonido.

Ah, y la codificación de GPU es terrible. Es difícil acertar, y lo que es "correcto" para una arquitectura de GPU puede estar muy, muy mal para otra. Y eso no es solo cambiar de AMD a NVIDIA; eso podría cambiar de una GeForce 250 a una GeForce 450. Eso es un cambio en la arquitectura básica. Y fácilmente podría hacer que su código no se ejecute bien. C ++ e incluso C no están permitidos; lo mejor que obtienes es OpenCL, que es algo así como C pero sin algunas de las sutilezas. Como la recursividad . Así es: no hay recurrencia en las GPU.

Depuración? Oh, espero que no le gusten las funciones de depuración de su IDE, porque ciertamente no estarán disponibles. Incluso si está usando GDB, bese ese adiós. Tendrá que recurrir a la printfdepuración ... espere, no hay printfGPU. Por lo tanto, tendrá que escribir en las ubicaciones de memoria y hacer que el programa de código auxiliar de su CPU las lea de nuevo.

Así es: depuración manual . Buena suerte con eso.

Además, ¿esas útiles bibliotecas que usa en C / C ++? O tal vez eres más un tipo .NET, usando XNA y demás. O lo que sea. No importa, ya que no puedes usar ninguno de ellos en la GPU. Debe codificar todo desde cero. Y si tiene una base de código ya existente, difícil: es hora de reescribir todo ese código.

Así que sí. Es horrible hacerlo para cualquier tipo de juego complejo. Y ni siquiera funcionaría, porque los juegos simplemente no son lo suficientemente paralelos como para ayudar.

Nicol Bolas
fuente
21

Por qué no es tan fácil de responder: es importante tener en cuenta que las GPU son procesadores especializados que en realidad no están destinados para un uso generalizado como una CPU normal. Debido a esta especialización, no es sorprendente que una GPU pueda superar a una CPU por las cosas para las que fue específicamente diseñada (y optimizada), pero eso no significa necesariamente que pueda reemplazar la funcionalidad y el rendimiento completos de una CPU generalizada.

Sospecho que los desarrolladores no hacen esto por una variedad de razones, que incluyen:

  • Quieren que los gráficos sean lo más rápidos y de la mejor calidad posible, y el uso de recursos valiosos de GPU podría interferir con esto.

  • Es posible que deba escribirse un código específico de GPU, y esto probablemente introducirá una complejidad adicional en la programación general del juego (o aplicación) en cuestión.

  • Una GPU normalmente no tiene acceso a recursos como tarjetas de red, teclados, mouse y joysticks, por lo que de todos modos no es posible manejar todos los aspectos del juego.

En respuesta a la segunda parte de su pregunta: Sí, hay otros usos. Por ejemplo, proyectos como SETI @ Home (y probablemente otros proyectos BOINC) están utilizando GPU (como los de nVidia) para cálculos complejos de alta velocidad:

  Ejecute SETI @ home en su GPU NVIDIA
  http://setiathome.berkeley.edu/cuda.php

( Me gusta tu pregunta porque plantea una idea interesante ) .

Randolf Richardson
fuente
18

Las CPU son más flexibles, generalmente es más fácil programarlas, pueden ejecutar subprocesos individuales mucho más rápido.

Si bien las GPU modernas se pueden programar para resolver prácticamente cualquier tarea, solo obtienen una ventaja de velocidad cuando pueden utilizar su arquitectura paralela. Este suele ser el caso con tareas "simples" altamente repetitivas. Gran parte del código que escribimos se ramifica de manera demasiado impredecible para ejecutarse de manera eficiente en una GPU.

Además de todo esto, podría terminar pasando mucho tiempo optimizando el código para diferentes chips gráficos. Si bien OpenCL está disponible para hacer que el mismo código se ejecute en muchos chips gráficos diferentes, intercambiará algunas de las ventajas de velocidad para este lujo.

Desde la perspectiva del programador de juegos, generalmente también queremos que nuestro juego se ejecute en computadoras con tarjetas gráficas menores. Algunos de los chips integrados no tienen la programabilidad requerida, pero si lo hacen son tan lentos que no superarán al procesador por un margen muy grande, incluso para el tipo de trabajos en los que deberían ser buenos. Y, por supuesto, si utilizara una GPU de gama baja para un juego, tomaría la poder de procesamiento muy necesaria de la representación gráfica.

De hecho, las perspectivas son excelentes, pero cuando haces un juego en lugar de descifrar contraseñas, los problemas prácticos en la mayoría de los casos superan los beneficios.

aaaaaaaaaaaa
fuente
6

Las GPU son muy difíciles de programar. Debe buscar cómo ordenar una lista en una GPU . Muchas tesis tienen búsqueda para hacerlo.

Usar una CPU con un subproceso es fácil, usar subprocesos múltiples es más difícil, usar muchas computadoras con una biblioteca paralela ya que PVM o MPI es difícil y usar un gpu es lo más difícil.

Ellis
fuente
4

Además de lo que Randolf Richardson respondió, hay algunas funcionalidades que los procesadores de GPU no pueden manejar por sí mismos. Por ejemplo, la CPU procesa algunos de los comandos de administración de memoria gráfica, ya que la GPU no puede manejarlos.

Y hay otra gran razón, la GPU está diseñada para cálculos multiproceso. Esto significa que los fabricantes de GPU pueden agregar fácilmente núcleos siempre que quieran aumentar la potencia de cálculo. Pero hay muchas tareas que no se pueden dividir en problemas más pequeños, como calcular el enésimo número de la serie de Fibonacci . En estas situaciones, la CPU es mucho más rápida ya que está más optimizada para tareas de subproceso único.

Ali1S232
fuente
4

Hay muchas respuestas que sugieren que las GPU son solo más rápidas porque manejan tareas en paralelo. Esto está exagerando un poco el problema. Las GPU pueden ser más eficientes por otros motivos, como poder tener un acceso a la memoria más restrictivo, no tener que admitir tantos tipos de datos, tener un conjunto de instrucciones más eficiente, etc. Las GPU tempranas todavía solo podían dibujar 1 píxel a una vez, pero fue el hecho de que podían hacer 1 cada ciclo lo que era importante.

La verdadera diferencia es que son 2 tipos diferentes de máquinas que están personalizadas para desempeñarse bien en diferentes categorías de tareas que parecen similares pero en realidad son bastante diferentes. Es como comparar un avión con un automóvil. El avión tiene una velocidad máxima mucho más alta, pero tiene más restricciones sobre cómo se puede usar. En las ocasiones en que puede hacer el mismo viaje con cualquier tipo, el avión parece superior.

Kylotan
fuente
La analogía sobre el avión es muy buena (+1), pero con respecto a las CPU que admiten diferentes tipos de datos, en realidad es más un concepto de lenguaje de nivel superior ya que las CPU (al menos en el espacio de Intel) tienden a tratar datos en formas muy básicas (por ejemplo, bits, bytes, palabras, palabras clave, etc.). Hay algunas instrucciones de circuito cerrado para escanear o copiar datos que terminan con un byte cero, pero los datos en estos casos no son realmente reconocidos por la CPU como un tipo particular (aparte de ser un fragmento de datos terminado en cero) en el contexto de estos bucles).
Randolf Richardson
@Randolf: las CPU tienen diferentes instrucciones y registros que tratan con diferentes tipos de datos de bajo nivel (por ejemplo, con signo versus sin signo, integral vs. punto flotante). Este es el caso en 8086 y, de hecho, en la mayoría de las arquitecturas modernas, y no es totalmente gratuito.
Kylotan
Estoy seguro de que todavía hacen mucho procesamiento lineal en la arquitectura subyacente. Desde el punto de vista de la programación, solo se necesita una instrucción para la GPU, pero los núcleos no se ejecutan exactamente en paralelo debido a su dependencia de otro hardware que no es paralelo, como la lectura de la memoria, probablemente la GPU puede proporcionar datos a un solo núcleo en un momento.
Pablo Ariel
3

Los desarrolladores no utilizan las GPU para todas las funciones que son buenos. Usan CPU para todas las funciones en las que son buenos. ¿Qué te hace pensar que no?

Las GPU son buenas en tareas que se pueden paralelizar masivamente y requieren grandes cantidades de cómputo con bajos requisitos de memoria o alta correlación temporal con solo pequeñas cantidades de toma de decisiones. Esto incluye renderizar imágenes, simulaciones físicas (partículas, colisión, tela, agua, reflejo), etc. Entonces, esto es precisamente para lo que los juegos modernos usan la GPU.

Las CPU son buenas en tareas que no se paralelan bien y requieren grandes cantidades de toma de decisiones. Pueden tolerar altos requisitos de memoria incluso con una correlación temporal moderada. Esto incluye inteligencia artificial, interfaz de usuario, disco y red de E / S, etc. Entonces, esto es precisamente para lo que los juegos modernos usan la CPU.

David Schwartz
fuente
1

Readback es otra razón por la que se me ocurre preferir ocasionalmente la CPU. No en términos de ancho de banda (ya que el ancho de banda de GPU-> CPU no es tanto un problema en el hardware moderno) sino en términos de estancamiento de la tubería. Si necesita recuperar los resultados de un cálculo y hacer algo interesante o útil con ellos, usar la GPU no es una buena elección (en el caso general, habrá casos especiales en los que puede seguir siendo apropiado) ya que la lectura siempre requerirá la GPU para detener lo que sea que esté haciendo, vaciar todos los comandos pendientes y esperar a que se complete la lectura. Esto puede matar el rendimiento en la medida en que no solo elimina el beneficio de usar la GPU, sino que en realidad puede ser considerablemente más lento.

Maximus Minimus
fuente
0

Este es un hilo viejo, pero este artículo recientemente publicado puede responder esta pregunta. Este documento, publicado en ACM Computing Surveys 2015, muestra que cada una de las CPU y GPU tiene sus ventajas únicas y, por lo tanto, presenta un argumento para alejarse del paradigma de "debate CPU vs GPU" al paradigma de "cómputo colaborativo CPU-GPU".

Una encuesta de las técnicas de computación heterogéneas CPU-GPU

usuario984260
fuente