Sugerencias para optimizar la CPU y la GPU

En este documento, se muestra cómo optimizar el rendimiento del juego con herramientas para identificar y resolver los cuellos de botella de la CPU y la GPU.

Optimización de la CPU

Si el análisis muestra que el juego está limitado por la CPU, es fundamental realizar una investigación más detallada. Para ello, es necesario identificar los subprocesos o las APIs específicos que causan cuellos de botella y reducen los FPS.

Por lo general, una solución universal no es eficaz para la optimización de la CPU. En su lugar, debes identificar la carga de trabajo más exigente según el juego o la escena y, luego, optimizar la lógica y las funciones pertinentes.

Herramientas de registro de tiempo del motor de juego

Las siguientes herramientas pueden ayudarte con este análisis:

Estadísticas irreales

En los proyectos de Unreal Engine, la herramienta Unreal Insight facilita el análisis de la información de registro de tiempo para los subprocesos individuales que componen un fotograma.

A modo de ilustración, el GameThread suele utilizar la mayor proporción de tiempo de CPU, lo que se atribuye principalmente al tiempo de tick. Además, una parte importante del tiempo de ticks se consume en tareas asociadas a FActorComponentTickFunction.

Para optimizar FActorComponentTick, es fundamental excluir los cálculos y aplicar la eliminación de personajes y objetos que se encuentran fuera del campo de visión de la cámara. Además, aprovechar las animaciones basadas en el LOD (nivel de detalle) puede generar más mejoras en el rendimiento.

Cronograma de seguimiento de Unreal Insight que muestra los tiempos de ejecución de GameThread, RenderThread y RHIThread
Registro de seguimiento de Unreal Insight con GameThread, RenderThread y RHIThread (haz clic para ampliar).

Unity Profiler (Unity)

El análisis con Unity Profiler revela que el subproceso principal consume más de 45 ms, y PostLateUpdate.FinishFrameRendering ocupa 16.23 ms, lo que la convierte en la operación que requiere más tiempo. Dentro de este, se observan varias invocaciones de Inl_RenderCameraStack. Es recomendable determinar la necesidad de las cámaras habilitadas y optimizarlas según corresponda.

Cronograma del generador de perfiles de Unity que muestra el subproceso principal en espera de Gfx.WaitForPresentOnGfxThread
Ejemplo de vinculación de GPU para Unity Profiler (haz clic para ampliar).

Herramientas de generación de perfiles a nivel del sistema

Usa las siguientes herramientas de generación de perfiles:

Perfetto

Con el registro de Perfetto, puedes determinar las asignaciones de núcleos de CPU y los detalles de ejecución de cada subproceso en un dispositivo con Android. Esto te permite identificar cuellos de botella en el rendimiento analizando los datos de ejecución de subprocesos.

Caso de sobrecarga de CPU

El registro indica que la carga de trabajo en GameThread y RenderThread está causando demoras en QueuePresent de RHI Thread, lo que genera una situación vinculada a la CPU, según VSync.

Registro de Perfetto que muestra los tiempos de ejecución de GameThread, RenderThread y RHIThread
Registros de Perfetto con detalles de ejecución de la CPU (haz clic para ampliar).

Caso de sobrecarga de GPU

El registro indica que la finalización de la GPU en sí supera los 25 ms, lo que significa una situación vinculada a la GPU.

Registro de Perfetto que muestra el bloque de finalización de la GPU en espera de la finalización de la GPU
Registros de Perfetto con detalles de la sobrecarga de la GPU (haz clic para ampliar).

Simpleperf

Para identificar las funciones con el mayor uso actual de CPU, se puede utilizar simpleperf. Para obtener resultados óptimos, se recomienda ordenar estas funciones para priorizar y abordar primero las que tienen el mayor uso.

Salida de Simpleperf que muestra las funciones con el mayor uso de CPU
Perfil de CPU de Simpleperf: Análisis de la jerarquía de llamadas a funciones y la utilización de recursos (haz clic para ampliar).

Simpleperf te ayuda a examinar datos sobre las funciones que usan la mayor cantidad de tiempo de CPU. Para optimizar el uso de la CPU, comienza con las funciones que usan más CPU. En este ejemplo, USkeletalMeshComponent, que se asocia con la animación en ActorComponentTickFunctions, usa la mayor cantidad de CPU.

Optimización de la GPU

Si el análisis muestra que el juego está vinculado a la GPU, es fundamental realizar una investigación adicional. Esto requiere el uso de diversas herramientas y técnicas para la optimización y el análisis de la GPU.

Para optimizar la GPU, usa un depurador de fotogramas para analizar la canalización de renderización y las llamadas de dibujo de cada escena. Además, debes comprender a fondo la arquitectura de la GPU y el comportamiento de la canalización para identificar las operaciones innecesarias o las áreas que se pueden optimizar.

En las siguientes secciones, se explican los métodos y las herramientas para la optimización de la GPU.

Elimina los RenderPasses innecesarios

Para mejorar el rendimiento de la renderización y reducir la carga de trabajo de la GPU, elimina los pases de renderización innecesarios. Esto incluye cualquier pase de renderización que no tenga llamadas de dibujo o cuyo resultado no se use en el fotograma final.

Usa un depurador de GPU, como RenderDoc, para analizar la canalización de renderización e identificar oportunidades de optimización.

  1. No hay llamadas de dibujo: Verifica si el pase de renderización incluye alguna llamada de dibujo. Si no tiene llamadas de dibujo, quita el pase.

  2. Salida sin usar: Verifica si los pases posteriores acceden a las salidas de los pases de renderización o las muestran, por ejemplo, el color o la profundidad. Si no es así, quita el pase.

  3. Pases combinables: Identifica los pases que puedes combinar:

    • El mismo búfer de fotogramas o los mismos archivos adjuntos
    • Operaciones de carga o almacenamiento compatibles
    • No hay barreras de dependencia entre ellas
Navegador de eventos de RenderDoc que muestra los pases de renderización y las llamadas de dibujo de Vulkan
Secuencia de comandos de RenderPass y GPU en RenderDoc (haz clic para ampliar).

Minimiza las operaciones de carga o almacenamiento

Las operaciones de carga o almacenamiento requieren muchos recursos porque usan mucha memoria. Minimiza las operaciones de carga y almacenamiento innecesarias. Realiza estas acciones solo cuando se requieran archivos adjuntos dentro de un RenderPass. De lo contrario, reemplázalas por operaciones Clear o Don't care para reducir la sobrecarga.

Optimización

Usa un depurador de GPU, como RenderDoc, para analizar la canalización de renderización e identificar las siguientes oportunidades de optimización:

  1. Carga: Si un archivo adjunto de pase de renderización no usa datos de un pase o archivo adjunto anterior, no es necesaria una operación de carga. En estos casos, usar Don't care o Clear puede reducir la sobrecarga.

  2. Almacenamiento: Si no se usa un archivo adjunto de pase de renderización después del pase de renderización actual, la operación de almacenamiento es innecesaria. En esos casos, usa Don't care o Clear.

  3. Reemplazar: Determina si la configuración actual de carga o almacenamiento se puede reemplazar por Clear o Don't Care sin afectar el fotograma final.

Navegador de eventos y el inspector de recursos de RenderDoc que analizan el diseño de la imagen y los pases de renderización
Análisis de la canalización de renderización de RenderDoc (haz clic para ampliar).

Evita el descarte para habilitar Early-Z

Early-Z mejora el rendimiento en plataformas móviles. Sin embargo, una instrucción discard dentro de un sombreador inhabilita automáticamente Early-Z. Si la instrucción discard no es esencial, quítala.

Aceleración de Early-Z

Esta optimización reduce significativamente las operaciones del sombreador de fragmentos y mejora el rendimiento de la GPU.

Early-Z Pruebas de profundidad y estencil

Tabla que compara las métricas de rendimiento de la CPU y la GPU cuando Early-Z está habilitado y cuando está inhabilitado
Impacto en el rendimiento de la aceleración de Early-Z (haz clic para ampliar).

Optimización

Usa un depurador de GPU, como RenderDoc, para analizar la canalización de renderización e identificar las siguientes oportunidades de optimización:

  1. Uso de discard en sombreadores de fragmentos: La palabra clave discard evita que la GPU realice pruebas de profundidad anticipadas, ya que la visibilidad del fragmento no se conoce de antemano.

  2. Modificación de gl_FragDepth: La modificación dinámica de gl_FragDepth cambia la profundidad de un fragmento, lo que inhabilita la optimización de Early-Z porque la profundidad final se desconoce antes del procesamiento del fragmento.

  3. Habilitado de alfa a cobertura: Cuando se habilita de alfa a cobertura (a menudo se usa en la renderización de MSAA), la cobertura de fragmentos depende de los valores alfa. Esto puede retrasar las pruebas de profundidad y, también, inhabilitar Early-Z.

Comparación de fragmentos por píxel con y sin la palabra clave del sombreador de descarte
Depurador de GPU de RenderDoc para el análisis (haz clic para ampliar).

Optimiza el formato de la textura

La selección óptima del formato de textura reduce el consumo de memoria, mejora la eficiencia del ancho de banda y optimiza el rendimiento del procesamiento. El uso de formatos con una precisión excesivamente alta puede desperdiciar recursos de GPU sin proporcionar ventajas visuales.

Optimización

Usa un depurador de GPU, como RenderDoc, para analizar la canalización de renderización e identificar las siguientes oportunidades de optimización:

  1. Usa D24S8 en lugar de D32S8 para los búferes de profundidad y estencil: El uso de D24S8 para los búferes de profundidad y estencil reduce el consumo de memoria en un 20% en comparación con D32S8, con poca o ninguna diferencia notable en la calidad visual en la mayoría de las aplicaciones.
  2. Usa la compresión ASTC para las texturas de color: La compresión ASTC reduce significativamente el uso de memoria de textura (hasta 8 veces en comparación con los formatos sin comprimir) y, al mismo tiempo, conserva una alta calidad visual.
  3. Usa formatos de medio punto flotante en lugar de punto flotante completo: Usa R16F o RG16F para reducir el ancho de banda de la memoria y el consumo de almacenamiento. Estos formatos son adecuados para los búferes de posprocesamiento.

Optimiza la complejidad de la geometría

Minimizar la complejidad geométrica mejora el rendimiento de la renderización, en especial en dispositivos móviles con capacidades de GPU limitadas. Esto implica usar una cantidad reducida de vértices y triángulos, consolidar objetos para disminuir las llamadas de dibujo y eliminar la geometría innecesaria o que no se renderiza. Las técnicas como la simplificación de la malla, el nivel de detalle (LOD) y el descarte por frustum o por oclusión pueden reducir significativamente la carga de trabajo de la GPU y aumentar la velocidad de fotogramas.

Optimización

Usa herramientas de generación de perfiles y depuradores de GPU, como RenderDoc, Android GPU Inspector o cualquier otro analizador de rendimiento, para identificar cuellos de botella relacionados con la geometría.

  1. Reduce Triangle Count: Minimiza el uso de polígonos, en especial para objetos pequeños o distantes.

  2. Usa el nivel de detalle (LOD): Según la distancia de la cámara, se usan automáticamente mallas más simples.

  3. Merge Small Meshes: Consolida objetos estáticos para reducir las llamadas de dibujo y la sobrecarga de la CPU.

  4. Frustum and Occlusion Culling: Evita renderizar objetos que están fuera de la vista o que están ocultos por otros elementos.

Quita los archivos adjuntos innecesarios

Los archivos adjuntos de pases de renderización (por ejemplo, color, profundidad, esténcil) consumen ancho de banda de memoria y recursos de GPU, incluso si no se usan. Quitar los archivos adjuntos innecesarios o redundantes mejora el rendimiento y reduce el consumo de energía, en especial en las plataformas para dispositivos móviles.

Optimización

Usa herramientas de generación de perfiles y depuradores de GPU, como RenderDoc, Android GPU Inspector o cualquier otro analizador de rendimiento, para identificar cuellos de botella relacionados con la geometría.

  1. Verifica el uso real: ¿Hay llamadas de dibujo o sombreadores que escriban en el archivo adjunto o lean desde él?
  2. Analiza el resultado del fotograma: Usa RenderDoc o utilidades comparables para determinar si el adjunto contribuye a la imagen final.
  3. Considera usar archivos adjuntos transitorios o ficticios: Los archivos adjuntos transitorios o una operación de almacenamiento "Don't Care" se deben usar para los datos temporales que no requieren almacenamiento persistente.

Optimiza la precisión del sombreador

Usar una precisión excesivamente alta (por ejemplo, highp en lugar de mediump o lowp) en los sombreadores aumenta la carga de trabajo de la GPU, el consumo de energía y la presión de registros, en especial en las GPU para dispositivos móviles. Si usas la precisión adecuada más baja para las variables (por ejemplo, posiciones, colores, UV), puedes mejorar el rendimiento sin un impacto visual perceptible.

Tabla que compara las métricas de rendimiento de la CPU y la GPU cuando se usa la precisión del sombreador mediump en comparación con highp
Impacto en el rendimiento de la precisión del sombreador (haz clic para ampliar).

Optimización

Usa herramientas de generación de perfiles y depuradores de GPU, como RenderDoc, Android GPU Inspector o cualquier otro analizador de rendimiento, para identificar cuellos de botella relacionados con la geometría.

  1. Revisa el código del sombreador: Evalúa las variables del sombreador y confirma que se use una alta precisión solo cuando sea necesario, como para los cálculos de profundidad o de espacio de pantalla. Usa una precisión media o baja para los colores, las coordenadas UV o los valores que no requieren una precisión alta.

  2. Usa depuradores de GPU: Las utilidades de diagnóstico, como RenderDoc o los generadores de perfiles de GPU para dispositivos móviles (por ejemplo, AGI, Mali/GPU Inspector), identifican el uso elevado de registros o las detenciones del sombreador asociadas con problemas de precisión.

El generador de perfiles de uso variable de Mali muestra la interpolación de 16 bits junto con el código del sombreador que usa mediump
Ejemplo de herramientas de generación de perfiles y depuradores de GPU (haz clic para ampliar).

Habilita el descarte de caras posteriores

A menudo, no es necesario renderizar los triángulos que no están orientados hacia la cámara (caras posteriores) para los objetos sólidos.

Optimización

El uso de VK_CULL_MODE_NONE puede afectar negativamente el rendimiento, ya que obliga a la GPU a renderizar las caras frontales y posteriores, lo que aumenta la carga de trabajo de renderización.

Registro de comandos de Vulkan que muestra vkCmdSetCullMode establecido en VK_CULL_MODE_NONE
Registros de depuración con eliminación de caras posteriores (haz clic para ampliar).

Cómo minimizar la superposición en escenas de la IU

Elimina las llamadas de dibujo y los pases de renderización innecesarios, en especial en las escenas de la IU, para mejorar el rendimiento de la renderización y reducir la carga de trabajo de la GPU. Por ejemplo, en una escena de IU en la que se renderiza todo el mundo antes de superponer la IU en la pantalla, el renderizado del mundo se vuelve redundante.

Optimización

Usa un depurador de GPU, como RenderDoc, para analizar la canalización de renderización e identificar las siguientes oportunidades de optimización:

  1. Verifica la ausencia de sobrepintado superfluo. En los contextos de la interfaz de usuario, en los que se puede renderizar toda la pantalla, confirma que los pases de renderización anteriores no se hayan sobregirado innecesariamente.
  2. Habilita las pruebas de profundidad y el descarte para optimizar el rendimiento.
  3. Considera el orden de renderización de adelante hacia atrás.
El navegador de eventos y el visualizador de texturas de RenderDoc identifican un pase de renderización de sobreimpresión innecesario
Ejemplo para eliminar llamadas de dibujo y pases de renderización superfluos (haz clic para ampliar).