NVIDIA CUDA en WSL2 + Docker Windows

Josué Acevedo Maldonado
12 min readDec 11, 2021

Sin morir en el intento … o casi.

El Subsistema de Windows para Linux (WSL) es una función de Windows que permite a los usuarios ejecutar aplicaciones, contenedores y herramientas de línea de comandos nativas de GNU/Linux.

Nota: Si desea saltarse la explicación, puede ir a la sección Instalación.

WSL

¿Por qué WSL?

Los sistemas operativos funcionan de forma diferente en su interior, esa es la explicación por la cual las aplicaciones son construidas de forma específica para cada uno de ellos. Sin embargo, en la actualidad esta división de aplicaciones entre sistemas operativos comienza a desaparecer y pueden darse ocasiones en las cuales las personas que tienen Windows necesitan utilizar aplicaciones que solamente funcionan en GNU/ Linux.

De forma tradicional para resolver este problema, se recurría a las máquinas virtuales como solución, sin embargo, el uso de una máquina virtual traía problemas de rendimiento, además de que era necesario contar con una máquina con muchos recursos para que pudiese funcionar de forma adecuada además de requerir la instalación y configuración de un software de administración de virtualización para administrar las máquinas virtuales invitadas.

Con el tiempo, empezaron a hacer su aparición tecnologías o técnicas como los contenedores, para reducir precisamente la cantidad de recursos necesarios para ejecutar aplicaciones en distintos entornos de los sistemas operativos. Los contenedores se componen de todas las dependencias de las aplicaciones, como bibliotecas, archivos, etc., que se agrupan para el desarrollo y la implementación fácil y predecible. Los contenedores se ejecutan en el sistema operativo que está instalado en el sistema directamente y, por lo tanto, no proporcionan un aislamiento total de otros contenedores como lo hace una máquina virtual, y tampoco requieren virtualizar el hardware de la maquina donde se ejecutan por lo que representan una sobrecarga insignificante como resultado.

Cuento con un post que trata el tema de los contenedores, si es que desea conocer un poco más sobre el tema (https://josueacevedo.medium.com/docker-una-breve-introducci%C3%B3n-6b9fd47cbda3).

WSL2

Microsoft ha planteado una solución intremedia de virtualización, colocando dentro del propio sistema operativo Windows, un núcleo de Linux; e integrándolo de tal forma que sea perfectamente transparente para las aplicaciones como para los desarrolladores el uso del hardware de la máquina, de tal forma que da la impresión de que las aplicaciones de GNU/Linux se ejecutan de forma nativa en Windows.

Aunque WSL es en sí mismo una máquina virtual, a diferencia de las máquinas virtuales tradicionales, es fácil de configurar, ya que se encuentra perfectamente integrado en Windows y es bastante ligero. Las aplicaciones que se ejecutan dentro de WSL tienen menos sobrecarga en comparación con las VM tradicionales, especialmente si requieren acceso al hardware o realizan operaciones privilegiadas en comparación con cuando se ejecutan directamente en el sistema. Esto es especialmente importante para cargas de trabajo aceleradas por GPU.

WSL2 es la segunda generación de WSL que ofrece los siguientes beneficios:

  • Las aplicaciones de Linux pueden ejecutarse tal cual en WSL2. WSL 2 es característicamente una máquina virtual con un kernel de WSL de Linux que proporciona compatibilidad total con el kernel de Linux convencional, lo que permite la compatibilidad con aplicaciones nativas de Linux, incluidas las distribuciones populares de Linux.
  • Soporte de sistema de archivos más rápido y más rendimiento.
  • WSL 2 está estrechamente integrado con el sistema operativo Microsoft Windows, lo que le permite ejecutar aplicaciones Linux junto con otras aplicaciones de escritorio y tiendas modernas de Windows, e incluso interoperarlas con ellas.

GPU en WSL

Los desarrolladores de Microsoft brindan soporte de hardware de GPU real a los contenedores WSL2 a través de la tecnología GPU-PV, donde el kernel de gráficos del sistema operativo (dxgkrnl) ordena las llamadas de los componentes en modo de usuario que se ejecutan dentro de la VM invitada al controlador del modo de kernel que vive en el host.

Microsoft desarrolló esta tecnología como una característica de su modelo de controlador de gráficos WDDM hace varias versiones de Windows con la ayuda de proveedores de hardware independientes (IHV). Todas las GPU NVIDIA compatibles actualmente pueden exponerse al sistema operativo Windows que se ejecuta dentro de un invitado de VM Hyper-V.

Para que WSL 2 pudiera aprovechar la potencia de GPU-PV, Microsoft tuvo que implementar la base de su marco gráfico dentro del invitado Linux: el modelo WDDM con el protocolo GPU-PV. El nuevo controlador de Microsoft se encuentra detrás del soporte para el modelo WDDM en Linux, llamado dxgkrnl. También está disponible como proyecto de código fuente en el repositorio WSL2-Linux-Kernel GitHub.

Se espera que el controlador dxgkrnl brinde soporte para la aceleración de GPU a los contenedores WSL 2 con la versión 2.9 de WDDM. Microsoft explica que dxgkrnl es un controlador de GPU de Linux basado en el protocolo GPU-PV y no comparte nada más en común con su contraparte de Windows que el nombre.

(Tomado de https://docs.nvidia.com/cuda/wsl-user-guide/index.html, 10/12/2021)

GPU-PV en acción

La biblioteca dxcore (libdxcore) proporciona una función API para enumerar los adaptadores de gráficos en el sistema que son compatibles con WDDM. Está destinado a ser el reemplazo multiplataforma de bajo nivel para la enumeración del adaptador DXGI tanto en Windows como en Linux.

Dxcore también se comunica con el controlador dxgkrnl (drivers/gpu/dxgkrnl) de Linux, mediante un conjunto de llamadas IOCTL privadas (IOCTL en Linux y llamadas GDI en Windows) con la API de capa D3DKMT, que es utilizada por CUDA y otros componentes de modo de usuario que dependen del soporte del modelo WDDM en WSL.

El controlador dxgkrnl además, se encarga de exponer el dispositivo /dev/dxg al modo de usuario en el invitado Linux,

Según Microsoft, la biblioteca dxcore (libdxcore.so) estará disponible tanto en Windows como en Linux. NVIDIA planea agregar soporte para DirectX 12 y CUDA API al controlador, apuntando a la nueva función WSL del modelo WDDM 2.9. Ambas bibliotecas de API se vincularán al dxcore para que puedan indicar al kernel dxg (dxgkrnl) de Linux que ordene sus solicitudes al KMD en el host.

La versión invitada de Linux de dxgkrnl se conecta al kernel dxg de Windows utilizando múltiples canales de bus de VM. El kernel dxg de Windows trata los envíos de procesos de Linux de la misma manera que los envíos de procesos de aplicaciones nativas de Windows que se ejecutan en el modelo WDDM. Estas peticiones las envía al KMD (un controlador de modo kernel específico provisto por cada fabricante de GPU’s), que los prepara y los envía al hardware de la GPU.

CUDA en WSL2

Ilustración de las posibilidades con la pila de software NVIDIA CUDA en WSL 2 (Tomado de https://docs.nvidia.com/cuda/wsl-user-guide/index.html, 10/12/2021)

En mayo de 2020, Microsoft anuncio una nueva función en WSL2, la aceleración de GPU, permitiendo ejecutar aplicaciones nativas de GNU/LINUX que hacen uso del hardware de una GPU en Windows.

Para más información, consulte DirectX que llegará al subsistema de Windows para Linux y al directorio WSL2-Linux-Kernel/driver/gpu en GitHub.

Para aprovechar la GPU en WSL 2, el sistema de destino debe tener instalado un controlador de GPU que admita el modelo WDDM de Microsoft . Estos controladores los proporcionan los proveedores de hardware de GPU como NVIDIA.

CUDA le permite programar en una GPU NVIDIA y ha sido compatible con el modelo WDDM en gráficos de Windows durante décadas. El nuevo contenedor Microsoft WSL 2 ofrece aceleración de GPU, que CUDA puede aprovechar para permitirle ejecutar cargas de trabajo CUDA dentro de WSL. Para obtener más información, consulte la Guía del usuario de CUDA en WSL .

El equipo de desarrollo de controladores de NVIDIA agregó soporte para el modelo WDDM y GPU-PV al controlador CUDA, para poder ejecutarlo en Linux en Windows.

Si es necesario utilizar estas GPU en el contenedor, se consulta la ubicación del almacén de controladores, una carpeta que contiene todas las bibliotecas de controladores tanto para el host de Windows como para WSL 2, mediante libdxcore.so. Depende de libnvidia-container.so configurar el contenedor para que el almacén de controladores se asigne correctamente y realice la configuración para las bibliotecas centrales compatibles con WSL2 GPU.

El soporte del controlador NVIDIA para WSL 2 no se detiene con CUDA y la pila de software de cómputo asociada. Hay compatibilidad con DirectX para habilitar gráficos en WSL2 al admitir las API DX12 junto con la compatibilidad con Direct ML. Para ver algunos ejemplos útiles, consulte https://docs.microsoft.com/en-us/windows/win32/direct3d12/gpu-tensorflow-wsl .

WSL2 permite que el uso de la GPU se comparta sin problemas entre las aplicaciones de Windows y Linux, lo cual ofrece flexibilidad y versatilidad, al mismo tiempo que hace más accesible la computación acelerada por GPU.

Instalación

Requisitos

  • La aceleración de GPU WSL2 esta disponible en las tarjetas de arquitectura Pascal y posteriores, en SKU de productos GeForce y Quadro en modo WDDM.

Yo tengo una NVIDIA GeForce GTX 1650.

  • Asegúrese de estar en el kernel WSL más reciente o al menos la 4.19.121+. Se recomienda lo version 5.10.16.3 o posterior para un mejor rendimiento y correcciones funcionales.
  • Tener Windows 11 o Windows 10 version 21H2, también conocido como “Actualización de noviembre de 2021 de Windows 10".

En mi caso utilizo Windows 10 21H2.

Para obtener la versión de Windows, se puede usar el comando winver en la consola de comandos.

winver

También, es posible descargar la imagen ISO de Windows 10 21H2 desde el siguiente enlace: https://www.microsoft.com/en-us/software-download/windows10 , para realizar una instalación limpia.

Paso 1: NVIDIA Driver CUDA en WSL

Descargue e instale el NVIDIA Drivers for CUDA on WSL en su sistema operativo Windows con una tarjeta GeForce o NVIDIA RTX/Quadro.

Paso 2: Instalar WSL2

Inicie su terminal de Windows favorito Símbolo del sistema/Powershell, e instale WSL

wsl

Paso 3: Actualizar WSL2

Asegúrese de tener el kernel WSL más reciente. El número de versión de WSL2 debe ser 4.19.121 o superior.

wsl --update

Si necesita reiniciar WSL2 después de instalar una actualización, utilice la bandera — shutdown, esto es necesario porque cerrar la ventana no apaga la distribución.

wsl --shutdown

Paso 4: Agrege el repositorio de sotfware de NVIDIA en WSL2

  • Abra su termina favorita de Windows e inicie WSL
wsl
  • Agregue la llave pública de los repositorios de paquetes de NVIDIA
sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
  • Agregue NVIDIA al directorio de fuentes de origen
sudo sh -c 'echo "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 /"> /etc/apt/sources.list.d/cuda.list'
  • Actualice la lista de paquetes de WSL
sudo apt-get update

Paso 5: Instalar NVIDIA CUDA Toolkit 11 en WSL2

NVIDIA CUDA Toolkit 11 es una colección de herramientas que se utilizan para crear, construir y ejecutar programas acelerados por CUDA. Incluye bibliotecas, compiladores, herramientas, muestras y documentación aceleradas por CUDA. También puede ser necesario combinarlo con kits de herramientas anteriores para usar programas que no son compatibles. Hay bibliotecas en los kits de herramientas NVIDIA CUDA más antiguos que también son necesarias.

sudo apt-get --yes install cuda-toolkit-11-0 cuda-toolkit-10-2

Paso 6: Instalar las herramientas de aprendizaje profundo en WSL2

  • Agregue el directorio de fuentes de origen
sudo sh -c 'echo "deb http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 /" > /etc/apt/sources.list.d/nvidia-machine-learning.list'
  • Actualice la lista de paquetes de WSL
sudo apt-get update
  • Instalación de las librerías
sudo apt-get install --yes --no-install-recommends cuda-10-2 libcudnn7=7.6.5.32-1+cuda10.2 libcudnn7-dev=7.6.5.32-1+cuda10.2

Paso 7 (Opcional): Instalar las herramientas de Tensores RT en WSL2

TensorRT es un kit de desarrollo de software, que se utiliza para optimizar modelos previamente entrenados para inferencias de alto rendimiento, en ciertas tarjetas gráficas NVIDIA.

sudo apt-get install --yes --no-install-recommends libnvinfer6=6.0.1-1+cuda10.2 libnvinfer-dev=6.0.1-1+cuda10.2 libnvinfer-plugin6=6.0.1-1+cuda10.2

Paso 8: Ejecute uno de los ejemplos

  • Vaya al directorio BlackScholes
cd /usr/local/cuda-11.0/samples/4_Finance/BlackScholes
  • Ejecute el MakeFile
sudo make
  • Ejecute el programa de ejemplo
./BlackScholes

CUDA + WSL + DOCKER

Este capítulo describe el flujo de trabajo para configurar el software necesario en WSL2 como preparación para ejecutar contenedores acelerados por GPU.

Instale nvidia-docker2 en WSL

  • Realice la instalación de la herramienta nvidia-docker2 en WSL, con los siguientes comandos
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.listcurl -s -L https://nvidia.github.io/libnvidia-container/experimental/$distribution/libnvidia-container-experimental.list | sudo tee /etc/apt/sources.list.d/libnvidia-container-experimental.listsudo apt-get update
sudo apt-get install -y nvidia-docker2

Inicie docker en WSL2

Para utilizar docker debe arrancar primero el demonio de Docker en WSL.

sudo dockerd

Este comando bloqueará la terminal, por lo que deberá abrir otra ventana para continuar trabajando.

Nota: El bloqueo de la terminal me parece algo poco eficiente, si descubro una forma de automatizar el arranque de Docker actualizare esta publicación

En otra ventana, ejecutemos un programa de ejemplo CUDA N-body. El ejemplo ya ha sido colocado en un contenedor y se encuentra disponible en NGC.

docker run --rm  --gpus all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark

Otro ejemplo que podemos ejecutar, es un contenedor de Ubuntu 20.04, en el que ejecutaremos el comando nvidia-smi.

docker run --rm --env NVIDIA_DISABLE_REQUIRE=1 --gpus all nvidia/cuda:11.4.2-devel-ubuntu20.04 nvidia-smi

Nota: la bandera — env NVIDIA_DISABLE_REQUIRE=1 , era necesaria en versiones anteriores de nvidia-docker2 para habilitar la GPU; en las últimas versiones ya NO es necesaria y de colocarse Docker solo la ignora.

Conectar Docker Windows a WSL2

Para poder utilizar la instrucción Docker en Windows y que este a su vez se conecte y utilice el entorne de WSL2 que hemos configurado hasta ahora, seguí los pasos de esta guía.

En ella, se recomendaba instalar la versión 3.3.0 de Docker desktop; sin embargo, en mi caso no funciono y mediante prueba y error, sobre todo error me tope con los problemas:

“exec: \”nvidia-smi\”: executable file not found in $PATH”

nvidia wls2 initialization error: driver error: failed to process request: unknown.

System has not been booted with systemd as init system (PID 1). Can’t operate.

Por la que como ultima opción actualice Docker desktop a su última versión mediante la opción ‘Check for Updates’ de la herramienta. Lo que instalo la version 4.3.0 en mi computadora.

y al hacer la prueba en la terminal de Windows:

docker run --rm --env NVIDIA_DISABLE_REQUIRE=1 --gpus all nvidia/cuda:11.4.2-devel-ubuntu20.04 nvidia-smi

FUNCIONO!!!!

Ahora puedo ejecutar contenedores de Docker, que utilizan la GPU NVIDIA en Windows que se conecta al WSL2. :)

Josue Acevedo Maldonado is a software engineer, currently working as a consultant.

Connect in LinkedIn.

Thank you for being part of the community!
You can find related content on the channel YouTube, Twitter, Twitch, Spotify, etc, besides the book Ensamblador X86.

Finally, if you have enjoyed this article and feel that you have learned something valuable, please share so others can learn from it as well.

Thanks for reading!

--

--

Josué Acevedo Maldonado

Amante de la tecnologia y con pasion en resolver problemas interesantes, consultor, y creador del canal de youtube NEOMATRIX. https://linktr.ee/neomatrix