Esta es una pregunta general sobre un tema que he encontrado interesante como jugador: cuellos de botella y programación de CPU / GPU. Si no me equivoco, he llegado a comprender que tanto la CPU como la GPU calculan cosas, pero esa es mejor en algunos cálculos que la otra debido a la diferencia en la arquitectura. Por ejemplo, descifrar hashes o minería de criptomonedas parece mucho más eficiente en las GPU que en las CPU.
Entonces me he preguntado: ¿es inevitable tener una GPU al 100% de carga mientras que la CPU está al 50% (por ejemplo)?
O, más precisamente: ¿Pueden algunos cálculos que normalmente realiza la GPU la CPU si el primero tiene una carga del 100%, de modo 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 me puedan dar!
fuente
NO-OP
s al mismo tiempo, lo que hará que ambos tengan una carga del 100%.Respuestas:
Teóricamente sí, pero prácticamente raramente vale la pena.
Tanto las CPU como las GPU están completas , por lo que cualquier algoritmo que pueda ser calculado por uno también puede ser calculado por el otro. La pregunta es qué tan rápido y qué tan conveniente.
Si bien la GPU es excelente para hacer los mismos cálculos simples en muchos puntos de datos de un gran conjunto de datos, 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 quitarle el trabajo al otro cuando se está estancando realmente no conduciría a un aumento notable en el rendimiento.
Sin embargo, el precio que debe pagar por esto es que debe 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 errores muy oscuros e imposibles de reproducir de este truco.
fuente
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, por ejemplo, al usar OpenCL o CUDA , puede cargar su GPU y su CPU cerca del 100%. Es muy probable que necesite escribir diferentes piezas de código para la GPU (llamado código "kernel") y para la CPU, y algún código de pegamento aburrido (especialmente para enviar a la GPU el código del kernel compilado).
Sin embargo, el código sería complejo y probablemente deba ajustarlo al hardware particular en el que se está ejecutando, en particular porque la transmisión de datos entre GPU y CPU es costosa.
Lea más sobre computación heterogénea .
Consulte también OpenACC , compatible con versiones recientes de GCC (por ejemplo, GCC 6 en junio de 2016)
fuente
Desde el punto de vista de la supercomputación, es mejor no pensar en la carga de la CPU / GPU en porcentaje, sino determinar cuántas operaciones necesita su problema en cuestión y luego compararlo con el rendimiento máximo del sistema.
Si obtiene un 100% de utilización de la CPU, no necesariamente significa que obtendrá 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. Su CPU de escritorio probablemente tenga una unidad fuera de servicio que reordenará las declaraciones para beneficiarse de tales superposiciones. O si tienes el siguiente programa:
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 todavía mostrará el 100%.
Entonces tiene características SIMD en las CPU que son operaciones vectoriales. Es como GPGPU-light en el sentido de que generalmente solo tiene cuatro u ocho operaciones al mismo tiempo, las GPU hacen 32 o 64. Sin embargo, debe usar eso para arrancar los FLOPS.
Cosas como el intercambio falso pueden generar un alto costo de sincronización que generalmente aparece como carga del kernel en Linux. La CPU se usa por completo, pero no tiene un rendimiento muy ú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, por lo tanto, es difícil de programar de manera eficiente. Tendrá que usar la jerarquía completa hasta SIMD y SMT (Intel llama a esto HyperThreading) para obtener el rendimiento.
Y luego la red a menudo te limita. Por lo tanto, resulta que es más rápido en tiempo (reloj de pared) calcular cosas en múltiples CPU al mismo tiempo en lugar de comunicarlo 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 por los números sin procesar.
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 Lattice QCD en un par de meses.
fuente
Puede que le interese comprobar el motor del navegador Servo que se está desarrollando en Mozilla Research y, más específicamente, su Web Render (video) .
Si bien cambiar una tarea de CPU a GPU dinámicamente puede no ser práctico, como se menciona en otras respuestas (especialmente @ Philip's), puede ser práctico estudiar de antemano la carga de CPU / GPU en cargas de trabajo típicas y cambiar algunas tareas a las generalmente menos cargadas uno.
En el caso de Web Render, la novedad es que tradicionalmente los navegadores realizan la mayor parte de su trabajo de renderizado en la CPU (es decir, la CPU se usa para calcular qué objetos mostrar, dónde cortar, etc.). La GPU normalmente es mejor en eso ... excepto que no todos los casos de uso son triviales de implementar (eliminación parcial, sombras, ... y texto).
Una versión inicial de Web Render demostró ser muy exitosa en el aumento del 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 tiene menos limitaciones y, en particular, es compatible con la representación de texto.
El objetivo, por supuesto, es descargar la mayor cantidad posible del proceso de renderización a la GPU, dejando a la CPU libre para ejecutar Javascript, actualizar el DOM y todas las demás tareas.
Por lo tanto, aunque no es tan extremo como su sugerencia, va en la dirección de diseñar una estrategia de cálculo teniendo en cuenta tanto la CPU como la GPU.
fuente
Con un enfoque en los juegos (ya que lo mencionó específicamente en su publicación), hay algunas formas en que puede equilibrar la carga. Un ejemplo es "desollar", es decir, animar un modelo. Para cada cuadro a renderizar, debe generar las matrices de transformación para cada cuadro 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 cuadros para obtener un movimiento suave , a menos que desee que su animación se vea como el Quake original (es decir, desigual).
En esta situación, puede hacerlo en la CPU y cargar los resultados en la GPU para renderizar, o hacer el cálculo y renderizar en la GPU. Creo que hoy en día se hace en la GPU (conocida como "skinning de hardware"): tiene sentido hacerlo dado que tiene cálculos relativamente simples que deben realizarse miles de veces, y cada vértice puede calcularse simultáneamente desde el resultado del vértice A no tiene relación con el resultado del vértice B.
Sin embargo, en teoría, podría cambiar dinámicamente entre hacerlo en la CPU o GPU dependiendo de qué tan sobrecargadas estén 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 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 versiones anteriores) es que tienes poco control sobre cómo la GPU interpreta tu código de sombreador. La ramificación dentro de un sombreador es arriesgada porque si accidentalmente crea una dependencia entre los cálculos, la GPU puede decidir comenzar a renderizar sus píxeles uno por uno, convirtiendo 60 fps a 10 fps en un instante a pesar de que los datos reales serán idénticos.
fuente
Un ejemplo del mundo real es el motor de renderizado LuxRender de código abierto , que es capaz de cargar completamente una CPU y GPU al mismo tiempo. Además, puede cargar múltiples GPU al mismo tiempo y también puede distribuirse en múltiples computadoras.
LuxRender usa OpenCL para facilitar esto, aunque también existen compilaciones sin OpenCL.
Esto es práctico porque los algoritmos que utiliza LuxRender son altamente paralelizables. El algoritmo más común que utiliza LuxRender es el trazado de ruta , donde muchas rutas de luz individuales se pueden calcular de forma independiente, una situación ideal para la computación de GPU y una que no requiere sincronización compleja entre nodos de computación. Sin embargo, las limitaciones de las GPU (cantidades menores de memoria, falta de soporte para algunas características de renderizado complejas y falta general de disponibilidad para algunos artistas) aseguran que el soporte de CPU sigue siendo esencial.
fuente
Sí, ciertamente es posible.
Cualquier cálculo que pueda hacer una CPU, 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, ramificación), por lo que debe escribir un código separado para maximizar el rendimiento.
Las GPU de rentabilidad son, en conjunto, mucho más potentes que las CPU. La idea general de las GPU es usar procesadores más baratos, más lentos, pero más numerosos para realizar cálculos mucho más rápido que las CPU por el mismo costo. Las GPU son más eficientes en cuanto a costos en uno o dos órdenes de magnitud.
Si logra que su algoritmo se ejecute en GPU, tiene más sentido optimizarlo y agregar tantos como necesite.
fuente