Optimización del uso de la GPU (múltiples GPU) y opciones opencl disponibles

Lo primero que no sé si éste es el mejor sitio para poner este hilo, si los mods creen que hay otra ubicación mejor, por favor que lo muevan (es posible que esté mejor en la sección de tutoriales y wiki, pero creo que no me deja crearlo ahí).

Introducción

Muchos de nosotros tenemos dos GPU (aunque algunos no lo sepan).
Si tienes un procesador intel Core que no sea F, incorporan una GPU (Intel graphics HD) no muy potente (utiliza la memoria del ordenador y no memoria dedicada) pero sí lo suficiente como para ayudar a realizar los previews de las imágenes o crear thumbnails.

En procesadores AMD los procesadores mobile y los desktop que acaban en G o GE tienen también una tarjeta gráfica incorporada que puedes aprovechar para procesar las imágenes.

Si tienes una tarjeta gráfica añadida, ya tienes dos GPU, la incorporada en el procesador y la tarjeta discreta (AMD o Nvidia) además de la propia CPU para procesar las imágenes y crear los previews y thumnails.

La cuestión es cómo configurar las GPU para un uso óptimo de las mismas y optimizar el rendimiento, lo que es realmente complejo en darktable y requiere hacer pruebas.

Voy a compartir con vosotros cómo he configurado yo darktable y el uso de las GPU y de paso así veo si creéis que es la mejor configuración o hay otra más óptima (yo tampoco soy experto en esto).

Prerequisitos

Darktable programa bastante potente, que hace uso de la GPU si está disponible y si no usa la CPU para procesar las imágenes.
Para que darktable pueda utilizar la GPU ésta tiene que se compatible con opencl (la mayoría lo son desde hace ya bastante años) y tiene que estar instalado en compilador de opencl de la tarjeta (normalmente no hay nada que hacer, al instalar los drivers de la tarjeta ya te instala opencl y todo lo necesario).
En linux el proceso de instalar opencl puede ser algo más complejo. Suele ser necesario instalar los drivers propietarios del fabricante de la tarjeta y no drivers opensource, para que así el rendimiento de la tarjeta se bueno y el opencl esté optimizado para las características de la tarjeta.
En algunos linux esto puede ser más o menos complicado, debido a que priorizan la instalación de drivers opensource (como puede ser el caso de debian).
Como yo darktable lo utilizo en windows, no puedo proporcionar en esto mucha más información, tendréis que recurrir a otras fuentes si tenéis problemas instalando los drivers de vuestra tarjeta y opencl.
Tenéis que aseugaros de que los drivers de la tarjeta funcionan adecuadamente y soportan opencl y de que en la BIOS, por supuesto, está la tarjeta habilitada.

Cuadro de diálogo de preferencias de Darktable

En el manual de darktable hay una sección explicando cómo configuar opencl y cómo activarlo:
darktable 3.6 user manual - activating opencl in darktable

Hay que abrir el cuadro de diálogo de preferencias y seleccionar la opción cpu/gpu/memory asegurándose de que esté activada la opción “Activar el soporte de opencl”
Si no tienes ninguna gpu decente capaz de ejecutar opencl (es demasiado antigua) o tiene problemas de compatibilidad entonces deja opencl desactivado (usará la cpu para todo, lo que es más lento, pero si tu tarjeta no es compatible, no hay otra opción).

Hay otra opción que pone “Perfil de programación de opencl”

Hay tres opciones: por defecto, Múltiples GPU y GPU muy rápida.

La opción a escoger depende de las gpu que tengas:

  • Por defecto: usará la configuración que darktable crea más apropiada, combinando la CPU y las GPUs que tengas, pudiendo ajustarlo mediante el parámetro ‘opencl_device_priority’ de darktablerc (más adelante lo comentaremos).

  • Múltiples GPU: esta opción la has de usar si tienes varias GPU activas y son de similar potencia y características. Si activas esta opción, darktable usará indistintamente la primer gpu disponible y non utilizará la CPU para ninguna de las operaciones.

  • GPU muy rápido: esta opción usará para todo únicamente una de las GPU, la GPU por defecto (habrá escogido como GPU por defecto la más capaz). Es una opción a escoger cuando una de las GPU es muy rápida y puede llevar a cabo todo el procesamiento de forma mucho más veloz que el resto de GPU/CPU presentes.

En el caso de tener varias GPU pero con diferentes capacidades (una discreta bastante capaz y la integrada en el procesador, por ejemplo) es mejor seleccionar la opción “Por defecto” y luego configurar manualmente el uso de las diferentes GPU/CPU.

Configuración personalizada con múltiples GPU

Como digo, hoy día suele ser habitual que tengamos más de una GPU en nuestro ordenador: una la de la tarjeta gráfica y otra escondida en el procesador (o es puede ser que tengas otra GPU antigua que no uses y quieras usarla para ayudar a acelerar el procesado de imágenes de darktable por tener una tarjeta no excesivamente potente que hace que darktable no vaya todo lo rápido que deseamos).

En este apartado comentaremos cómo configurar darktable editando el fichero de configuración para seleccionar qué tarea asignarle a cada tarjeta.
En este caso la opción de las preferencias “perfil de programación de OpenCL” ha de estar en “Por defecto” y el soporte OpenCL activado.

Si tienes un procesador que incorpore una GPU y la deseas utilizar, lo primero es asegurarse de que dicha GPU está habilitada (o activada) en la BIOS de tu ordenador.
Al instalar una tarjeta gráfica externa, es posible que se haya deshabilitado la GPU del procesador en la BIOS.
Entra en la BIOS y comprueba que está activada la GPU incorporada en el procesadro (o en algunas ocasiones puede ser la placa la que lo incorpore). Cada BIOS es diferente, por lo que tendrás que investigar o leer el manual de la placa, normalmente se puede acceder a la configuración presionando la tecla “Del” durante el proceso de arranque (en el momento que aparece en pantalla un mensaje indicándolo).

El siguiente paso será editar el fichero de configuración de darktable denominado darktablerc que se encuentra en el directorio de configuración del programa (que se puede establecer mediante la opcion de linea de comandos --configdir), junto con la base de datos.
Por defecto en windows se encuentra en %LOCALAPPDATA%\darktable, donde %LOCALAPPDATA% en windows suele ser por defecto C: \Users <inicio de sesión de usuario>\ AppData\ Local (para más información sobre los directorios de darktable consultar el mágnífico artículo Los archivos de configuración y de funcionamiento de Darktable - Tutoriales - Wiki - Artículos - darktable en español de nuestro compañero @Oscar).
Darktable deshabilita por defecto algunos modelos de GPU que han comprobado en algún momento que daban problemas.

En concreto en windows (creo que en linux no) deshabilitan las tarjetas Intel que utilicen los drivers NEO de Intel (la mayoría de las GPU integradas en placa).
Esto se debe a que las implementaciones iniciales propietarias de opencl en los drivers de Intel parece que eran defectuosas y daban problemas (en windows).

Sin embargo esto ya ha sido solucionado por intel en las últimas versiones de sus drivers, drivers que han pasado a ser de código abierto basados en los drivers desarrollados para linux.

Sin embargo los desarrolladores de darktable no se han animado a eliminar a NEO de la lista negra, por no haberse hecho las pruebas suficientes (no muchos de los desarrolladores usan windows).
Sin embargo en las pruebas que yo he hecho con los nuevos drivers, no he encontrado problemas.

Para habilitar los drivers opencl en estas tarjetas/CPU de Intel hay que editar darktablerc y buscar la opción opencl_disable_drivers_blacklist poniéndola en TRUE.
Ha de quedar así:

opencl=TRUE
...
opencl_disable_drivers_blacklist=true
....
opencl_scheduling_profile=default

Si tu GPU no es Intel o no está metida en la lista negra no hace falta que cambies eso.

El siguiente paso es indicarle a darktable a qué tarea dedicar cada una de las GPU existentes y la CPU.
Esa información está en el manual aquí: darktable 3.6 user manual - multiple devices

En darktable se necesitan hacer diferentes operaciones que pueden ser aceleradas por una GPU, que pueden ser englobadas en cuatro categorías de pixelpipes:

  1. Procesado completo de la imagen. Es el correspondiente al revelado principal de la imagen a tamaño completo, y que requiere más potencia de cálculo y por tanto conviene asignarle la GPU más potente.
  2. Generación de vistas previa. Son las vistas previas que se crean por ejemplo en la esquina superior izquierda del cuarto oscuro, a menor tamaño que la imagen principal y que por tanto pueden ser llevadas a cabo por GPUs no tan potentes.
  3. Generación de fichero exportados. Es el pixelpipe encargado de exportar una imagen a tamaño completo generando el fichero de salida aplicando todo el proceso de revelado. Requiere más potencia de cálculo, incluso más que el revelado a pantalla completa y por tanto conviene asignarle la GPU más potente.
  4. Generación de miniaturas. Cuando importamos imágenes en la mesa de luz o en determinadas ocasiones, darktable genera miniaturas que se guardan en el disco duro para poder se luego utilizadas. Es un proceso que no requiere tanta capacidad de cálculo y puede llevarse a cabo por GPU no tan potentes.

La configuración de las GPUs asignadas a cada tarea o pixelpipe se realiza cambiando el parámetro opencl_device_priority en el fichero de configuración (darktablerc).

Si quieres seleccionar manualmente la prioridad de la GPU a utilizar en cada una de las tareas anteriores, has de activar opencl y establecer el Perfil de programación opencl en Por defecto
O bien configurar los correspondientes parámetros en darktablerc:

opencl=TRUE
opencl_scheduling_profile=default

El formato a utilizar es:
opencl_device_priority=[1]/[2]/[3]/[4]

Donde cada uno de los bloques [n] es una lista de dispositivos GPU a utilizar para la tarea n (según el listado proporcionado anteriormente) separados por , y por orden de prioridad.
Se han de proporcionar las cuatro listas para cada una de las tareas de 1 a 4 proporcionadas anteeriormente y separadas una de otas mediante /.

Se puede emplear en nombre del dispositivo (tal y como se identifica dicho dispositivo ante el sistema, escrito exactamente igual) o el número que asigna darktable a cada uno de los dispositivos presentes. Lo más habitual es utilizar el número.

Cuando darktable ha de realizar una de las tareas anteriores, consulta la lista de dispositivos configurada en el anterior parámetro, empezando por el que hemos colocado en primero lugar (más a la izda).
Si un dispositivo está en ese momento ocupado con otra tarea (ya que un mismo dispositivo puede ser asignado a más de una tarea), pasa a utilizar el siguiente dispositivo de la lista (separada por comas) recorriéndola toda hasta que localiza un dispositivo que esté libre en ese momento.
Si todos los dispositivos están ocupados, pasa a utilizar la CPU.

Existen dos caracteres especiales que se pueden utilzar en la lista de dispositivos:

  • * (comodín): se utiliza para indicar que se puede utilizar cualquiera de las GPU disponibles en el sistema, el primero que no esté en uso.
  • ! (negación): se antepone al número o nombre de dispositivo para indicar que se salte dicho dispositivo y no sea utilizado para esa tarea.

Con estos caracteres se facilita y acorta el poder describir los dispositivos a utilizar.
Con el ! podremos evitar que darktable emplee la GPU más potente para la generación en segundo plano de miniaturas o los previews, que requieren menos recursos y no son tan prioritarias como la creación de la vista principal a plena pantalla. Esta GPU más potente y capaz, la reservaremos para la creación de dicha vista principal o la exportación, negándo su uso para las otras actividades.
De no hacerlo así cuando darktable tenga que exportar el fichero o generar la vista principal, se puede encontrar que la GPU más adecuada para ello está ocupada creando las miniaturas de segundo plano y tener que usar la GPU menos capacitada o la CPU, con la consiguiente merma en la velocidad de respuesta.

Para saber cuál es el número asignado a cada una de nuestras GPU por darktable, podemos ejecutar el comando:
darktable-cltest

Que se encuentra en el subdirectorio bin del directorio donde hallamos instalado darktable (en windows comunmente en C:\Program Files\darktable).

Como salida nos proporciona información sobre los diferentes dispositivos GPU encontrados en el sistema y el resultado de compilar los kernels opencl (los pequeños programas utilizados para acelerar el funcionamiento de los diferentes módulos de darktable) y si ha habido algún error.
Si encuentra algún error en la compilación, tenemos una versión no compatible o un dispositivo no compatible o que está en la lista negra (si no la hemos deshabilitado como se explicó anteriormente) dicho dispositivo será rechazado y eliminado de la lista por darktable, proporcionándonos finalmente la lista de dispositivos que utilizará.
En la salida propocionada por el programa hemos de buscar unas lineas como las que se muestran a continuación (que no se encuentran al final de la salida si no en medio, después de compilar los kernels para cada dispositivo y antes de los mensajes de carga en memoria de los mismos).

..........
18.617783 [opencl_init] OpenCL successfully initialized.
18.619967 [opencl_init] here are the internal numbers and names of OpenCL devices available to darktable:
18.624091 [opencl_init]         0       'GeForce GTX 1050 Ti'
18.626605 [opencl_init]         1       'Intel(R) UHD Graphics 630'
18.628886 [opencl_init] FINALLY: opencl is AVAILABLE on this system.
.........

En mi caso hay dos GPU: una la tarjeta dedicada GeForce que es la más potente de las dos y a la que le ha asignado el número 0, y otra la integrada en el procesador Intel a la que le ha asignado el 1.

La primera es una tarjeta con memoria gráfica integrada y una capacidad de proceso bastante superior a la integrada en la CPU que además utiliza la memoria compartida del sistema que es más lenta.

Por ello yo quiero dedicar la más rápida (la 0) a las operaciones de creación de la imagen principal y de exportación que son las que requieren más recurso y tendrán más impacto en el uso del programa durante la edición, evitando que se use para generar thumbnails o previews (lo que podría provocar que estuviera ocupada cuando darktable trate de buscar una GPU para generar la vista principal) y que la GPU integrado (la 1) a la generación de miniaturas en segundo plano o de las vista previa de la izda.

Por ello he utilizado la siguiente linea en darktablerc:

opencl_device_priority=!1,*/!0,*/0,*/*/!0,*
  • Con ello le indico que no utilice la 1 (más lenta) para la operación de generar la vista principal , y luego utilizo el * para indicarle que utilice cualquier otra disponible (primera de las listas !1,*).
  • En la generación de vista previa(!0,*) le indico que no utilice la GPU potente (la 0) para que así no pueda ocurrir que esté utilizando esa cpu para esta tarea cuando necesita crear la vista completa y acabe usando la CPU para esta tarea (ya que la 1 le hemos dicho que no la utilice). El * le indica que utilice cualquier otra GPU disponible (normalmente la 1 o si esta está ocupada, la CPU).
  • En la generación de ficheros exportados (tercera de las listas, 0,*) le indicamos que utilice preferentemente la 0, la más rápida, y si esta estuviera ocupada, pues cualquier otra GPU (la 1 o la CPU si no hay ninguna libre).
  • Por último en la generación de minituras (’ !0,*`) le indicamos al igual que en la vista previa que no utilice la GPU 0 y utilice cualquier otra disponible en ese momento.

Conclusiones

La configuración que nos pueda acelerar más el procesado y tratamiento de imágenes dependerá pues de las capacidades de nuestras tarjetas: si estas son similares, podremos usarlas de forma indistinta (y escogeremos la opción de múltiples GPU), si tenemos una GPU super potente, muy por encima de la capacidad de las otras GPU o de nuestro procesador, será mejor utilizar para todo esa GPU (escoger el perfil de GPU muy rápida).
Si tenemos varias GPU una más potente pero otras que también pueden aportar para acelerar el procesado de imágenes en segundo plano, tendremos que hacer pruebas para ver cuál es la configuración más adecuada en nuestro caso y configurar manualmente el parámetro opencl_device_priorityde darktablerc.

La verdad es que la opción que yo estoy utilizando desconozco si es la más efectiva para mi configuración y forma de uso de darktable (se admiten sugerencias).
Pero desde luego la activación de la GPU de intel y la configuración manual me ha proporcionado un incremento significativo en la velocidad de respuesta de darktable durante el procesado de imágenes.

Espero que esto sea útil a otros.

4 Me gusta

Bueno he tardado en acabarlo, pero al fin lo he hecho.
Con los comentarios sobre la configuracón del parámetro opencl_device_priority doy por finalizado el artículo.

Si tenéis comentarios que hacer o mejoras que proponer no dudéis en responder a este hilo.

Muchas gracias @ariznaf, guardado para cuando pueda usar los dos, de momento con la GPU va como un tiro (GEFORCE RTX 3070). Tengo alguna incompatibilidad con la AMD Radeon que trae el ordenador si activo las dos. Tengo que esperar a un nuevo kernel (linux)

Saludos.

Creo que si tienes ese pepino y suficiente memoria no necesitas complicarte.
Yo probaría con la opción de usar sólo una gpu (por supuesto esa).

Yo me conformo con las GTX (1050 y 1650). Las tarjetas nuevas se han puesto por las nubes. Y no digamos ya las nuevas de AMD.

Creo que el que se usen en minería de bitcoins tiene que ver con ello.

Pero bueno es cuestión de probar.
Y también de probar si te conviene desactivar la GPU 3070 para hacer thumbnails y previews y dejárselo al procesador.
Si no si DT se pone a hacer algo de eso y luego abres una foto y encuentra la GPU ocupada en esos menesteres utilizará la CPU para el trabajo duro (crear la vista completa o exportar) y lo notarás lento.

Si escoges usar una sola tarjeta, todo lo hará con la tarjeta y si está ocupada espera a que acabe una cosa para ponerse con otra.