¿Cómo puedo optimizar el rendimiento de un programa cuando no hay herramientas de creación de perfiles disponibles?

8

Actualmente estoy trabajando en un programa OpenGl cuyo rendimiento me gustaría mejorar. El rendimiento está bien, pero no es ideal en GPU dedicadas potentes, pero es abismal en gráficos integrados (<10 fps). En un programa normal (basado en CPU, sin OpenGl u otra API de GPU), ejecutaría un perfilador (tal vez el integrado en CLion) en el programa, vería dónde se pasa la mayor parte del tiempo y luego trabajaría en un mejor algoritmo para esas áreas o encuentre una manera de reducir la cantidad que se llama esa área.

El uso de esta técnica en mi programa OpenGl muestra que la gran mayoría del tiempo del programa (~ 86%) en su hilo principal (el que quiero optimizar) se gasta en el archivo .so del controlador OpenGl. Además, el uso de la CPU del programa mientras se ejecuta es muy bajo, pero el uso de la GPU oscila entre el 95% y el 100%. En conjunto, esta información me dice que el cuello de botella está en la GPU, por lo que es donde debería optimizar.

Esto donde ocurre un problema. Sin embargo, mi técnica normal de usar un perfilador para guiar mis optimizaciones no funcionará sin un perfilador de GPU específico. Como tal, investigué un poco para encontrar un generador de perfiles que me diga dónde se está gastando el tiempo de procesamiento de la GPU. No pude encontrar nada que se pueda utilizar de forma remota. Todo era solo para Windows (ejecuto exclusivamente Linux, y mi programa aún no se ha portado a Windows, ni lo será hasta que esté mucho más avanzado), ya no se actualiza y / o cuesta mucho más que el presupuesto para este proyecto es

Como tal, pregunto: ¿cómo puedo optimizar el rendimiento de mi programa cuando el generador de perfiles relevante no existe? Traté de adivinar dónde están los problemas y optimizar a partir de eso, sin embargo, no hizo ninguna diferencia a pesar de que pude determinar que mis optimizaciones (eliminación del frustum) resultaron en menos trabajo para la GPU a la mitad. Una buena respuesta dará alguna técnica de creación de perfiles que sea aplicable a Opengl en Linux, o dará una técnica que funcione sin un generador de perfiles.

john01dav
fuente
¿La forma audaz de comentar las cosas hasta que encuentres la parte lenta?
Ewan
@ewan el renderizador es bastante mínimo. Al comentar cualquier cosa, no funcionaría.
john01dav
En cuanto a la parte de "comentar cosas", puede dividir el código en secciones y luego comentar todo excepto la primera sección. Estas secciones deben tener algún resultado para verificar que funciona como se esperaba. Una vez que tenga eso, puede recorrer las secciones para ver si esa pieza es el cuello de botella potencial. Con este enfoque, terminará con el estilo básico de prueba y error de prueba.
eparham7861
Si tiene acceso a un pin de hardware en la GPU, puede alternarlo al entrar y salir de las funciones. Un osciloscopio luego indicará el tiempo dedicado a esa función y con qué frecuencia se llama, etc.
Ant

Respuestas:

7

¿Cómo puedo optimizar el rendimiento de mi programa cuando el generador de perfiles relevante no existe?

Al perfilar su código usted mismo. Encontrar cuellos de botella en la GPU no es particularmente difícil.

Suponiendo que tiene una versión inferior de OpenGL (las consultas del temporizador no están disponibles), entonces hace lo que la gente ha estado haciendo durante años: cambie las cosas y vea cómo funciona.

Hay tres ubicaciones básicas para los cuellos de botella en el renderizado: CPU (es decir: envío de datos de manera ineficiente), vértice T&L y procesamiento por fragmento. Determinar cuál es el cuello de botella es simplemente una cuestión de ver el impacto en el rendimiento cuando se cambia algo.

Por ejemplo, si desea ver si el procesamiento por fragmento es un cuello de botella, reduzca el número de fragmentos generados (es decir, la resolución de la pantalla). Si el rendimiento mejora a una velocidad lineal con respecto al número de píxeles en la resolución de la pantalla, entonces ese fue su cuello de botella.

Si desea saber si su procesamiento de vértices es el cuello de botella, renderice el mismo objeto varias veces (una después de la otra). Suponiendo que tiene una prueba de profundidad activa y no está haciendo una mezcla, los fragmentos de las representaciones posteriores deben seleccionarse antes de invocar el sombreador de fragmentos. Entonces, si el rendimiento cae linealmente al representar repetidamente todos los objetos, entonces tiene un cuello de botella de procesamiento de vértices.

Y si ninguno de esos es el cuello de botella, entonces, por proceso de eliminación, la CPU es el problema.

Si tiene acceso a consultas de temporizador, puede cronometrar las operaciones de GPU directamente. No puede cronometrar etapas específicas, pero puede determinar el tiempo que tardan en completarse los comandos de la GPU. También puede encontrar la latencia entre la finalización del comando GPU y cuando el hilo de la CPU terminó de enviar esos comandos. En general, esto debería ayudarlo a determinar cuánto tiempo le lleva a la GPU procesar cosas en comparación con la CPU que lo envía.

Nicol Bolas
fuente