En la programación de software, ¿sería posible tener cargas de CPU y GPU al 100%?

43

Esta es una pregunta general sobre un tema que me ha parecido interesante como jugador: cuellos de botella y programación de CPU / GPU. Si no me equivoco, entiendo que tanto la CPU como la GPU calculan cosas, pero esa es mejor en algunos cálculos que en la otra debido a la diferencia en la arquitectura. Por ejemplo, el craqueo de hashes o la minería de criptomonedas parece mucho más eficiente en las GPU que en las CPU.

Así que me he preguntado: ¿es inevitable tener una GPU con una carga del 100% mientras que la CPU está al 50% (por ejemplo)?

O, más precisamente: ¿La CPU puede realizar algunos cálculos que normalmente realiza la GPU si el primero tiene una carga del 100%, para que ambos alcancen una carga del 100%?

He buscado un poco sobre el tema, pero he vuelto con las manos vacías. ¡Creo y espero que esto tenga su lugar en esta subsección y estoy abierto a cualquier documentación o conferencia que pueda darme!

    
pregunta MadWard 24.06.2016 - 11:06

7 respuestas

62

Teóricamente sí, pero prácticamente no vale la pena.

Tanto las CPU como las GPU son turing-complete , por lo que cualquier algoritmo que pueda calcularse por uno también puede ser calculado por el otro. La pregunta es qué tan rápido y qué conveniente.

Si bien la GPU se distingue por hacer los mismos cálculos simples en muchos puntos de datos de un conjunto de datos grande, la CPU es mejor en algoritmos más complejos con muchas ramificaciones. Con la mayoría de los problemas, la diferencia de rendimiento entre las implementaciones de CPU y GPU es enorme. Eso significa que usar uno para tomar el trabajo del otro cuando está estancado realmente no llevaría a un aumento notable en el rendimiento.

Sin embargo, el precio que debe pagar por esto es que necesita programar todo dos veces, una para la CPU y otra para la GPU. Eso es más del doble de trabajo porque también tendrá que implementar la lógica de conmutación y sincronización. Esa lógica es extremadamente difícil de probar, porque su comportamiento depende de la carga actual. Espere muy oscuro e imposible reproducir errores de este truco.

    
respondido por el Philipp 24.06.2016 - 11:14
36

No está relacionado con la programación del juego. Algunos códigos científicos también pueden usar tanto la GPU como la CPU.

Con una programación cuidadosa y dolorosa, p. ej. utilizando OpenCL o CUDA , podría cargar tanto su GPU como su CPU cerca del 100%. Es muy probable que necesite escribir diferentes partes de código para la GPU (también llamado código del "kernel") y para la CPU, y un código de cola aburrido (especialmente para enviar a la GPU el código compilado del kernel).

Sin embargo, el código sería complejo y probablemente deba sintonizarlo con el hardware en particular en el que se está ejecutando, en particular porque la transmisión de datos entre GPU y amp; La CPU es costosa.

Lea más sobre computación heterogénea .

Vea también OpenACC , compatible con versiones recientes de GCC (por ejemplo, GCC 6 en junio de 2016)

    
respondido por el Basile Starynkevitch 24.06.2016 - 11:11
11

Desde un punto de vista de supercomputación, es mejor no pensar en la carga de CPU / GPU en porcentaje, sino más bien determinar cuántas operaciones necesita su problema y compararlas con el rendimiento máximo del sistema.

Si obtiene un 100% de utilización de la CPU, no significa necesariamente que obtenga todo el rendimiento del sistema. Las CPU a menudo pueden hacer varias cosas diferentes al mismo tiempo, digamos una división y una adición. Si puede comenzar la división temprano, posiblemente se puede superponer con la adición. Lo más probable es que su CPU de escritorio tenga una unidad fuera de servicio que reordene las declaraciones para beneficiarse de tales solapamientos. O si tienes el siguiente programa:

if (expr1)
    expr2;
else
    expr3;

Una CPU reordenada intentará calcular las tres expresiones al mismo tiempo y luego descartará el resultado de una de ellas. Esto lo hace más rápido en general. Si tiene algún bloqueador en su programa y no puede reordenar, entonces está utilizando menos carriles en la CPU, pero probablemente seguirá apareciendo al 100%.

Entonces tienes funciones SIMD en las CPU que son operaciones vectoriales. Es como GPGPU-light en el sentido de que normalmente solo tiene cuatro u ocho operaciones al mismo tiempo, las GPU hacen como 32 o 64. Aún así, tiene que usar eso para arrancar los FLOPS.

Cosas como el uso compartido falso pueden llevar a un alto costo de sincronización que generalmente aparece como carga del kernel en Linux. La CPU se utiliza por completo, pero no tiene un rendimiento útil.

He hecho algo de programación en una máquina IBM Blue Gene / Q. Tiene muchos niveles de jerarquía ( esquema de Blue Gene / L obsoleto) y es por lo tanto difícil de programar eficientemente. Tendrá que usar la jerarquía completa hasta SIMD y SMT (Intel llama a este HyperThreading) para obtener el rendimiento.

Y luego la red a menudo te limita. Por lo tanto, resulta que es más rápido en el tiempo (reloj de pared) calcular las cosas en varias CPU al mismo tiempo en lugar de comunicarse a través de la red. Esto pondrá más carga en las CPU y hará que el programa se ejecute más rápido. Pero el rendimiento real del programa no es tan bueno como parece a partir de los números en bruto.

Si agrega GPU a la mezcla, será aún más difícil organizar todo esto para obtener un rendimiento. Esa será una de las cosas que comenzaré a hacer en mi Tesis de Maestría de QCD de Lattice en un par de meses.

    
respondido por el Martin Ueding 24.06.2016 - 16:02
1

Es posible que le interese consultar el motor de navegador Servo que se está desarrollando en Mozilla Research, y más específicamente su Web Render (video) .

Si bien el cambio dinámico de una tarea de CPU a GPU puede ser poco práctico, como se mencionó en otras respuestas (especialmente @ Philip's), puede ser práctico estudiar la carga de CPU / GPU en cargas de trabajo típicas de antemano y cambiar algo tareas a las menos cargadas.

En el caso de Web Render, la novedad es que tradicionalmente los navegadores realizan la mayor parte de su trabajo de representación en la CPU (es decir, la CPU se utiliza para calcular qué objetos mostrar, dónde cortar, etc.). La GPU normalmente es mejor en eso ... excepto que no todas las casos de uso son triviales de implementar (eliminación parcial, sombras, ... y texto).

Una versión inicial de Web Render demostró ser altamente exitosa en el aumento de rendimiento, pero no trató de abordar el problema de la representación de texto (y tenía algunas otras limitaciones). Mozilla Research ahora está trabajando en una segunda versión que está destinada a tener menos limitaciones y, en particular, a admitir la representación de texto.

El objetivo, por supuesto, es descargar la mayor cantidad posible del proceso de renderizado a la GPU, dejando que la CPU se ejecute de forma gratuita para ejecutar Javascript, actualizar el DOM y todas las demás tareas.

Entonces, aunque no es tan extremo como su sugerencia, va en la dirección del diseño de una estrategia de cálculo teniendo en cuenta ambos CPU y GPU.

    
respondido por el Matthieu M. 24.06.2016 - 17:10
0

Con un enfoque en los juegos (ya que lo mencionaste específicamente en tu publicación), hay algunas maneras en que puedes equilibrar la carga. Un ejemplo es "skinning", es decir, animar un modelo. Para que se genere cada fotograma, debe generar las matrices de transformación para cada fotograma de animación y aplicarlo a los vértices del modelo para transformarlo en la pose en la que debe estar. También debe interpolar fotogramas para obtener un movimiento suave , a menos que desee que su animación se parezca al Quake original (es decir, desigual).

En esta situación, puede hacerlo en la CPU y cargar los resultados en la GPU para su procesamiento, o realizar el cálculo y la representación en la GPU. Creo que hoy en día se realiza en la GPU (conocida como "skin skinning"): tiene sentido hacerlo, ya que tiene cálculos relativamente simples que se deben realizar miles de veces, y cada vértice se puede calcular al mismo tiempo desde el resultado del vértice A no tiene relación con el resultado del vértice B.

Sin embargo, en teoría, puedes cambiar dinámicamente entre hacerlo en la CPU o GPU, dependiendo de la sobrecarga de la GPU y la CPU.

Sin embargo, el principal bloqueador para hacer esto en todos los cálculos es que la CPU y la GPU tienen diferentes fortalezas y debilidades. Los trabajos masivamente paralelos se realizan mejor en la GPU, mientras que las tareas lineales intensivas con ramificación se realizan mejor en la CPU. Solo unos pocos trabajos podrían realizarse de manera realista en ambos casos sin un impacto serio en el rendimiento.

En general, el principal problema con la programación de GPU (al menos con OpenGL y DirectX 11 y bajo) es que tiene poco control sobre cómo la GPU interpreta su código de sombreado. La ramificación dentro de un sombreador es arriesgada porque si crea accidentalmente una dependencia entre los cálculos, entonces la GPU puede decidir comenzar a renderizar los píxeles uno por uno, convirtiendo 60 fps a 10 fps en un instante, a pesar de que los datos reales se vuelvan idénticos.

    
respondido por el Richard Greenlees 24.06.2016 - 14:32
0

Un ejemplo del mundo real es el motor de representación de código abierto LuxRender , que es capaz de cargar completamente una CPU y GPU en al mismo tiempo. Además, puede cargar varias GPU al mismo tiempo y también puede distribuirse en varios equipos.

LuxRender utiliza OpenCL para facilitar esto, aunque también existen versiones sin OpenCL.

Esto es práctico porque los algoritmos que utiliza LuxRender son altamente paralelizables. El algoritmo más común que usa LuxRender es trazado de ruta , donde muchas rutas de luz individuales pueden calcularse independientemente una de la otra, una situación ideal para la computación de GPU y una que no requiere una sincronización compleja entre nodos de cómputo. Sin embargo, las limitaciones de las GPU (menor cantidad de memoria, falta de soporte para algunas funciones de representación complejas y falta general de disponibilidad para algunos artistas) aseguran que el soporte de la CPU sea esencial.

    
respondido por el PythonNut 26.06.2016 - 00:18
0

Sí, es ciertamente posible.

Cualquier cálculo que una CPU pueda hacer, una GPU también puede hacer, y viceversa.

Pero es poco común porque:

  • Complejidad de ingeniería Si bien es posible ejecutar el mismo código en una CPU y GPU (por ejemplo, CUDA), los procesadores tienen diferentes capacidades y características de rendimiento. Uno es MIMD; el otro, SIMD. Lo que es rápido en uno es lento en el otro (por ejemplo, la bifurcación), por lo que es necesario escribir código separado para maximizar el rendimiento.

  • Eficacia en costos Las GPU son en conjunto mucho más poderosas que las CPU. La idea general de las GPU es utilizar procesadores más baratos, más lentos, pero más numerosos para realizar cálculos mucho más rápidos que los CPU, por el mismo costo. Las GPU son más eficientes en cuanto a costos en uno o dos órdenes de magnitud.

Si consigue que su algoritmo se ejecute en GPU, tiene más sentido optimizarlos y agregar tantos como necesite.

    
respondido por el Paul Draper 26.06.2016 - 20:45

Lea otras preguntas en las etiquetas